Merge jdk7-b123
authorigor
Tue, 21 Dec 2010 18:45:45 -0800
changeset 3289869190935eed
parent 3288 36898b974d28
parent 3282 2dbd18b83bad
child 3290 83480217896c
child 3337 403a88eeac15
Merge
src/share/classes/java/dyn/BootstrapMethod.java
src/share/classes/java/dyn/LinkagePermission.java
src/share/classes/java/dyn/MethodHandleProvider.java
src/share/classes/sun/dyn/JavaMethodHandle.java
test/java/dyn/JavaDocExamples.java
     1.1 --- a/make/java/dyn/Makefile	Tue Dec 21 15:27:55 2010 -0800
     1.2 +++ b/make/java/dyn/Makefile	Tue Dec 21 18:45:45 2010 -0800
     1.3 @@ -36,9 +36,7 @@
     1.4  LANGUAGE_VERSION = -source 7
     1.5  CLASS_VERSION = -target 7
     1.6  
     1.7 -# Actually, it will be less disruptive to compile with the same
     1.8 -# -target option as the rest of the system, and just turn on
     1.9 -# the specific compiler option we need here:
    1.10 -OTHER_JAVACFLAGS = -XDinvokedynamic
    1.11 +# Tell the compiler not to accept transitional forms.
    1.12 +OTHER_JAVACFLAGS = -XDallowTransitionalJSR292=no
    1.13  
    1.14  include $(BUILDDIR)/common/Classes.gmk
     2.1 --- a/src/share/classes/java/dyn/BootstrapMethod.java	Tue Dec 21 15:27:55 2010 -0800
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,82 +0,0 @@
     2.4 -/*
     2.5 - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     2.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 - *
     2.8 - * This code is free software; you can redistribute it and/or modify it
     2.9 - * under the terms of the GNU General Public License version 2 only, as
    2.10 - * published by the Free Software Foundation.  Oracle designates this
    2.11 - * particular file as subject to the "Classpath" exception as provided
    2.12 - * by Oracle in the LICENSE file that accompanied this code.
    2.13 - *
    2.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 - * version 2 for more details (a copy is included in the LICENSE file that
    2.18 - * accompanied this code).
    2.19 - *
    2.20 - * You should have received a copy of the GNU General Public License version
    2.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 - *
    2.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 - * or visit www.oracle.com if you need additional information or have any
    2.26 - * questions.
    2.27 - */
    2.28 -
    2.29 -package java.dyn;
    2.30 -
    2.31 -import java.lang.annotation.*;
    2.32 -
    2.33 -/**
    2.34 - * Annotation on InvokeDynamic method calls which requests the JVM to use a specific
    2.35 - * <a href="package-summary.html#bsm">bootstrap method</a>
    2.36 - * to link the call.  This annotation is not retained as such in the class file,
    2.37 - * but is transformed into a constant-pool entry for the invokedynamic instruction which
    2.38 - * specifies the desired bootstrap method.
    2.39 - * <p>
    2.40 - * If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
    2.41 - * with a constructor which accepts a class, string, and method type.
    2.42 - * If the <code>value</code> and <code>name</code> are both given, there must be
    2.43 - * a static method in the given class of the given name which accepts a class, string,
    2.44 - * and method type, and returns a reference coercible to {@link CallSite}.
    2.45 - * <p>
    2.46 - * This annotation can be placed either on the return type of a single {@link InvokeDynamic}
    2.47 - * call (see examples) or else it can be placed on an enclosing class or method, where it
    2.48 - * determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
    2.49 - * specifically annotated with a bootstrap method.
    2.50 - * Every {@link InvokeDynamic} call must be given a bootstrap method.
    2.51 - * <p>
    2.52 - * Examples:
    2.53 -<blockquote><pre>
    2.54 -&#064;BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
    2.55 -String x = (String) InvokeDynamic.greet();
    2.56 -//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
    2.57 -&#064;BootstrapMethod(MyCallSite.class)
    2.58 -void example() throws Throwable {
    2.59 -    InvokeDynamic.greet();
    2.60 -    //BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
    2.61 -}
    2.62 -</pre></blockquote>
    2.63 - * <p>
    2.64 - */
    2.65 -@Target({ElementType.TYPE_USE,
    2.66 -            // For defaulting every indy site within a class or method; cf. @SuppressWarnings:
    2.67 -            ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR
    2.68 -            })
    2.69 -@Retention(RetentionPolicy.SOURCE)
    2.70 -public @interface BootstrapMethod {
    2.71 -    /** The class containing the bootstrap method. */
    2.72 -    Class<?> value();
    2.73 -
    2.74 -    /** The name of the bootstrap method.
    2.75 -     *  If this is the empty string, an instance of the bootstrap class is created,
    2.76 -     *  and a constructor is invoked.
    2.77 -     *  Otherwise, there must be a static method of the required name.
    2.78 -     */
    2.79 -    String name() default "";  // empty string denotes a constructor with 'new'
    2.80 -
    2.81 -    /** The argument types of the bootstrap method, as passed out by the JVM.
    2.82 -     *  There is usually no reason to override the default.
    2.83 -     */
    2.84 -    Class<?>[] arguments() default {Class.class, String.class, MethodType.class};
    2.85 -}
     3.1 --- a/src/share/classes/java/dyn/CallSite.java	Tue Dec 21 15:27:55 2010 -0800
     3.2 +++ b/src/share/classes/java/dyn/CallSite.java	Tue Dec 21 18:45:45 2010 -0800
     3.3 @@ -26,40 +26,45 @@
     3.4  package java.dyn;
     3.5  
     3.6  import sun.dyn.*;
     3.7 +import sun.dyn.empty.Empty;
     3.8 +import sun.misc.Unsafe;
     3.9  import java.util.Collection;
    3.10  
    3.11  /**
    3.12   * A {@code CallSite} is a holder for a variable {@link MethodHandle},
    3.13   * which is called its {@code target}.
    3.14 - * Every call to a {@code CallSite} is delegated to the site's current target.
    3.15 + * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
    3.16 + * all calls to the site's current target.
    3.17 + * A {@code CallSite} may be associated with several {@code invokedynamic}
    3.18 + * instructions, or it may be "free floating", associated with none.
    3.19 + * In any case, it may be invoked through an associated method handle
    3.20 + * called its {@linkplain #dynamicInvoker dynamic invoker}.
    3.21   * <p>
    3.22 - * A call site is initially created in an <em>unlinked</em> state,
    3.23 - * which is distinguished by a null target variable.
    3.24 - * Before the call site may be invoked (and before certain other
    3.25 - * operations are attempted), the call site must be linked to
    3.26 - * a non-null target.
    3.27 + * {@code CallSite} is an abstract class which does not allow
    3.28 + * direct subclassing by users.  It has three immediate,
    3.29 + * concrete subclasses that may be either instantiated or subclassed.
    3.30 + * <ul>
    3.31 + * <li>If a mutable target is not required, an {@code invokedynamic} instruction
    3.32 + * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
    3.33 + * <li>If a mutable target is required which has volatile variable semantics,
    3.34 + * because updates to the target must be immediately and reliably witnessed by other threads,
    3.35 + * a {@linkplain VolatileCallSite volatile call site} may be used.
    3.36 + * <li>Otherwise, if a mutable target is required,
    3.37 + * a {@linkplain MutableCallSite mutable call site} may be used.
    3.38 + * </ul>
    3.39   * <p>
    3.40 - * A call site may be <em>relinked</em> by changing its target.
    3.41 - * The new target must be non-null and must have the same
    3.42 - * {@linkplain MethodHandle#type() type}
    3.43 + * A non-constant call site may be <em>relinked</em> by changing its target.
    3.44 + * The new target must have the same {@linkplain MethodHandle#type() type}
    3.45   * as the previous target.
    3.46   * Thus, though a call site can be relinked to a series of
    3.47   * successive targets, it cannot change its type.
    3.48   * <p>
    3.49 - * Linkage happens once in the lifetime of any given {@code CallSite} object.
    3.50 - * Because of call site invalidation, this linkage can be repeated for
    3.51 - * a single {@code invokedynamic} instruction, with multiple {@code CallSite} objects.
    3.52 - * When a {@code CallSite} is unlinked from an {@code invokedynamic} instruction,
    3.53 - * the instruction is reset so that it is no longer associated with
    3.54 - * the {@code CallSite} object, but the {@code CallSite} does not change
    3.55 - * state.
    3.56 - * <p>
    3.57   * Here is a sample use of call sites and bootstrap methods which links every
    3.58   * dynamic call site to print its arguments:
    3.59  <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
    3.60 -&#064;BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
    3.61  static void test() throws Throwable {
    3.62 -    InvokeDynamic.baz("baz arg", 2, 3.14);
    3.63 +    // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
    3.64 +    InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
    3.65  }
    3.66  private static void printArgs(Object... args) {
    3.67    System.out.println(java.util.Arrays.deepToString(args));
    3.68 @@ -71,16 +76,15 @@
    3.69    printArgs = lookup.findStatic(thisClass,
    3.70        "printArgs", MethodType.methodType(void.class, Object[].class));
    3.71  }
    3.72 -private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
    3.73 +private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
    3.74    // ignore caller and name, but match the type:
    3.75 -  return new CallSite(MethodHandles.collectArguments(printArgs, type));
    3.76 +  return new ConstantCallSite(MethodHandles.collectArguments(printArgs, type));
    3.77  }
    3.78  </pre></blockquote>
    3.79   * @author John Rose, JSR 292 EG
    3.80   */
    3.81 -public class CallSite
    3.82 -    implements MethodHandleProvider
    3.83 -{
    3.84 +abstract
    3.85 +public class CallSite {
    3.86      private static final Access IMPL_TOKEN = Access.getToken();
    3.87  
    3.88      // Fields used only by the JVM.  Do not use or change.
    3.89 @@ -88,61 +92,47 @@
    3.90      private int        vmindex;  // supplied by the JVM (BCI within calling method)
    3.91  
    3.92      // The actual payload of this call site:
    3.93 -    private MethodHandle target;
    3.94 +    /*package-private*/
    3.95 +    MethodHandle target;
    3.96  
    3.97      // Remove this field for PFD and delete deprecated methods:
    3.98      private MemberName calleeNameRemoveForPFD;
    3.99  
   3.100      /**
   3.101 -     * Make a blank call site object.
   3.102 -     * Before it is returned from a bootstrap method, this {@code CallSite} object
   3.103 -     * must be provided with
   3.104 -     * a target method via a call to {@link CallSite#setTarget(MethodHandle) setTarget},
   3.105 -     * or by a subclass override of {@link CallSite#initialTarget(Class,String,MethodType) initialTarget}.
   3.106 +     * Make a blank call site object with the given method type.
   3.107 +     * An initial target method is supplied which will throw
   3.108 +     * an {@link IllegalStateException} if called.
   3.109 +     * <p>
   3.110 +     * Before this {@code CallSite} object is returned from a bootstrap method,
   3.111 +     * it is usually provided with a more useful target method,
   3.112 +     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
   3.113 +     * @throws NullPointerException if the proposed type is null
   3.114       */
   3.115 -    public CallSite() {
   3.116 +    /*package-private*/
   3.117 +    CallSite(MethodType type) {
   3.118 +        target = MethodHandles.invokers(type).uninitializedCallSite();
   3.119      }
   3.120  
   3.121      /**
   3.122       * Make a blank call site object, possibly equipped with an initial target method handle.
   3.123 -     * The initial target reference may be null, in which case the {@code CallSite} object
   3.124 -     * must be provided with a target method via a call to {@link CallSite#setTarget},
   3.125 -     * or by a subclass override of {@link CallSite#initialTarget}.
   3.126 -     * @param target the method handle which will be the initial target of the call site, or null if there is none yet
   3.127 +     * @param target the method handle which will be the initial target of the call site
   3.128 +     * @throws NullPointerException if the proposed target is null
   3.129       */
   3.130 -    public CallSite(MethodHandle target) {
   3.131 +    /*package-private*/
   3.132 +    CallSite(MethodHandle target) {
   3.133 +        target.type();  // null check
   3.134          this.target = target;
   3.135      }
   3.136  
   3.137 -    /** @deprecated transitional form defined in EDR but removed in PFD */
   3.138 -    public CallSite(Class<?> caller, String name, MethodType type) {
   3.139 -        this.calleeNameRemoveForPFD = new MemberName(caller, name, type);
   3.140 -    }
   3.141 -    /** @deprecated transitional form defined in EDR but removed in PFD */
   3.142 -    public Class<?> callerClass() {
   3.143 -        MemberName callee = this.calleeNameRemoveForPFD;
   3.144 -        return callee == null ? null : callee.getDeclaringClass();
   3.145 -    }
   3.146 -    /** @deprecated transitional form defined in EDR but removed in PFD */
   3.147 -    public String name() {
   3.148 -        MemberName callee = this.calleeNameRemoveForPFD;
   3.149 -        return callee == null ? null : callee.getName();
   3.150 -    }
   3.151 -    /** @deprecated transitional form defined in EDR but removed in PFD */
   3.152 +    /**
   3.153 +     * Report the type of this call site's target.
   3.154 +     * Although targets may change, the call site's type can never change.
   3.155 +     * The {@code setTarget} method enforces this invariant by refusing any new target that does
   3.156 +     * not have the previous target's type.
   3.157 +     * @return the type of the current target, which is also the type of any future target
   3.158 +     */
   3.159      public MethodType type() {
   3.160 -        MemberName callee = this.calleeNameRemoveForPFD;
   3.161 -        return callee == null ? (target == null ? null : target.type()) : callee.getMethodType();
   3.162 -    }
   3.163 -    /** @deprecated transitional form defined in EDR but removed in PFD */
   3.164 -    protected MethodHandle initialTarget() {
   3.165 -        return initialTarget(callerClass(), name(), type());
   3.166 -    }
   3.167 -
   3.168 -    /** Report if the JVM has linked this {@code CallSite} object to a dynamic call site instruction.
   3.169 -     *  Once it is linked, it is never unlinked.
   3.170 -     */
   3.171 -    private boolean isLinked() {
   3.172 -        return vmmethod != null;
   3.173 +        return target.type();
   3.174      }
   3.175  
   3.176      /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
   3.177 @@ -152,68 +142,66 @@
   3.178                             MethodType type,
   3.179                             MemberName callerMethod,
   3.180                             int        callerBCI) {
   3.181 -        if (this.isLinked()) {
   3.182 +        if (this.vmmethod != null) {
   3.183 +            // FIXME
   3.184              throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction");
   3.185          }
   3.186 -        MethodHandle target = this.target;
   3.187 -        if (target == null) {
   3.188 -            this.target = target = this.initialTarget(callerMethod.getDeclaringClass(), name, type);
   3.189 -        }
   3.190 -        if (!target.type().equals(type)) {
   3.191 +        if (!this.type().equals(type)) {
   3.192              throw wrongTargetType(target, type);
   3.193          }
   3.194          this.vmindex  = callerBCI;
   3.195          this.vmmethod = callerMethod;
   3.196 -        assert(this.isLinked());
   3.197      }
   3.198  
   3.199      /**
   3.200 -     * Just after a call site is created by a bootstrap method handle,
   3.201 -     * if the target has not been initialized by the factory method itself,
   3.202 -     * the method {@code initialTarget} is called to produce an initial
   3.203 -     * non-null target.  (Live call sites must never have null targets.)
   3.204 +     * Report the current linkage state of the call site, a value which may change over time.
   3.205       * <p>
   3.206 -     * The arguments are the same as those passed to the bootstrap method.
   3.207 -     * Thus, a bootstrap method is free to ignore the arguments and simply
   3.208 -     * create a "blank" {@code CallSite} object of an appropriate subclass.
   3.209 +     * If a {@code CallSite} object is returned
   3.210 +     * from the bootstrap method of the {@code invokedynamic} instruction,
   3.211 +     * the {@code CallSite} is permanently bound to that instruction.
   3.212 +     * When the {@code invokedynamic} instruction is executed, the target method
   3.213 +     * of its associated call site object is invoked directly.
   3.214 +     * It is as if the instruction calls {@code getTarget} and then
   3.215 +     * calls {@link MethodHandle#invokeExact invokeExact} on the result.
   3.216       * <p>
   3.217 -     * If the bootstrap method itself does not initialize the call site,
   3.218 -     * this method must be overridden, because it just raises an
   3.219 -     * {@code InvokeDynamicBootstrapError}, which in turn causes the
   3.220 -     * linkage of the {@code invokedynamic} instruction to terminate
   3.221 -     * abnormally.
   3.222 -     * @deprecated transitional form defined in EDR but removed in PFD
   3.223 -     */
   3.224 -    protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) {
   3.225 -        throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type);
   3.226 -    }
   3.227 -
   3.228 -    /**
   3.229 -     * Report the current linkage state of the call site.  (This is mutable.)
   3.230 -     * The value may not be null after the {@code CallSite} object is returned
   3.231 -     * from the bootstrap method of the {@code invokedynamic} instruction.
   3.232 -     * When an {@code invokedynamic} instruction is executed, the target method
   3.233 -     * of its associated {@code call site} object is invoked directly,
   3.234 -     * as if via {@link MethodHandle}{@code .invoke}.
   3.235 -     * <p>
   3.236 -     * The interactions of {@code getTarget} with memory are the same
   3.237 +     * Unless specified differently by a subclass,
   3.238 +     * the interactions of {@code getTarget} with memory are the same
   3.239       * as of a read from an ordinary variable, such as an array element or a
   3.240       * non-volatile, non-final field.
   3.241       * <p>
   3.242       * In particular, the current thread may choose to reuse the result
   3.243       * of a previous read of the target from memory, and may fail to see
   3.244       * a recent update to the target by another thread.
   3.245 -     * @return the current linkage state of the call site
   3.246 +     * <p>
   3.247 +     * In a {@linkplain ConstantCallSite constant call site}, the {@code getTarget} method behaves
   3.248 +     * like a read from a {@code final} field of the {@code CallSite}.
   3.249 +     * <p>
   3.250 +     * In a {@linkplain VolatileCallSite volatile call site}, the {@code getTarget} method behaves
   3.251 +     * like a read from a {@code volatile} field of the {@code CallSite}.
   3.252 +     * <p>
   3.253 +     * This method may not be overridden by application code.
   3.254 +     * @return the current linkage state of the call site, its target method handle
   3.255 +     * @see ConstantCallSite
   3.256 +     * @see VolatileCallSite
   3.257       * @see #setTarget
   3.258       */
   3.259 -    public MethodHandle getTarget() {
   3.260 +    public final MethodHandle getTarget() {
   3.261 +        return getTarget0();
   3.262 +    }
   3.263 +
   3.264 +    /**
   3.265 +     * Privileged implementations can override this to force final or volatile semantics on getTarget.
   3.266 +     */
   3.267 +    /*package-private*/
   3.268 +    MethodHandle getTarget0() {
   3.269          return target;
   3.270      }
   3.271  
   3.272      /**
   3.273       * Set the target method of this call site.
   3.274       * <p>
   3.275 -     * The interactions of {@code setTarget} with memory are the same
   3.276 +     * Unless a subclass of CallSite documents otherwise,
   3.277 +     * the interactions of {@code setTarget} with memory are the same
   3.278       * as of a write to an ordinary variable, such as an array element or a
   3.279       * non-volatile, non-final field.
   3.280       * <p>
   3.281 @@ -224,43 +212,32 @@
   3.282       * at any given call site.
   3.283       * @param newTarget the new target
   3.284       * @throws NullPointerException if the proposed new target is null
   3.285 -     * @throws WrongMethodTypeException if the call site is linked and the proposed new target
   3.286 +     * @throws WrongMethodTypeException if the proposed new target
   3.287       *         has a method type that differs from the previous target
   3.288 +     * @throws UnsupportedOperationException if the call site is
   3.289 +     *         in fact a {@link ConstantCallSite}
   3.290       */
   3.291      public void setTarget(MethodHandle newTarget) {
   3.292 +        checkTargetChange(this.target, newTarget);
   3.293 +        setTargetNormal(newTarget);
   3.294 +    }
   3.295 +
   3.296 +    void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
   3.297 +        MethodType oldType = oldTarget.type();
   3.298          MethodType newType = newTarget.type();  // null check!
   3.299 -        MethodHandle oldTarget = this.target;
   3.300 -        if (oldTarget == null) {
   3.301 -            // CallSite is not yet linked.
   3.302 -            assert(!isLinked());
   3.303 -            this.target = newTarget;  // might be null!
   3.304 -            return;
   3.305 -        }
   3.306 -        MethodType oldType = oldTarget.type();
   3.307 -        if (!newTarget.type().equals(oldType))
   3.308 +        if (!newType.equals(oldType))
   3.309              throw wrongTargetType(newTarget, oldType);
   3.310 -        if (oldTarget != newTarget)
   3.311 -            CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
   3.312      }
   3.313  
   3.314      private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
   3.315 -        return new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type);
   3.316 -    }
   3.317 -
   3.318 -    /** Produce a printed representation that displays information about this call site
   3.319 -     *  that may be useful to the human reader.
   3.320 -     */
   3.321 -    @Override
   3.322 -    public String toString() {
   3.323 -        return "CallSite"+(target == null ? "" : target.type());
   3.324 +        return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
   3.325      }
   3.326  
   3.327      /**
   3.328 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   3.329       * Produce a method handle equivalent to an invokedynamic instruction
   3.330       * which has been linked to this call site.
   3.331 -     * <p>If this call site is a {@link ConstantCallSite}, this method
   3.332 -     * simply returns the call site's target, since that will not change.
   3.333 +     * <p>If this call site is a {@linkplain ConstantCallSite constant call site},
   3.334 +     * this method simply returns the call site's target, since that will never change.
   3.335       * <p>Otherwise, this method is equivalent to the following code:
   3.336       * <p><blockquote><pre>
   3.337       * MethodHandle getTarget, invoker, result;
   3.338 @@ -271,8 +248,9 @@
   3.339       * @return a method handle which always invokes this call site's current target
   3.340       */
   3.341      public final MethodHandle dynamicInvoker() {
   3.342 -        if (this instanceof ConstantCallSite)
   3.343 -            return getTarget();  // will not change dynamically
   3.344 +        if (this instanceof ConstantCallSite) {
   3.345 +            return getTarget0();  // will not change dynamically
   3.346 +        }
   3.347          MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
   3.348          MethodHandle invoker = MethodHandles.exactInvoker(this.type());
   3.349          return MethodHandles.foldArguments(invoker, getTarget);
   3.350 @@ -287,9 +265,34 @@
   3.351          }
   3.352      }
   3.353  
   3.354 -    /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
   3.355 -    public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
   3.356 +    /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
   3.357 +    /*package-private*/
   3.358 +    static Empty uninitializedCallSite() {
   3.359 +        throw new IllegalStateException("uninitialized call site");
   3.360 +    }
   3.361  
   3.362 -    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
   3.363 -    public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
   3.364 +    // unsafe stuff:
   3.365 +    private static final Unsafe unsafe = Unsafe.getUnsafe();
   3.366 +    private static final long TARGET_OFFSET;
   3.367 +
   3.368 +    static {
   3.369 +        try {
   3.370 +            TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
   3.371 +        } catch (Exception ex) { throw new Error(ex); }
   3.372 +    }
   3.373 +
   3.374 +    /*package-private*/
   3.375 +    void setTargetNormal(MethodHandle newTarget) {
   3.376 +        target = newTarget;
   3.377 +        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
   3.378 +    }
   3.379 +    /*package-private*/
   3.380 +    MethodHandle getTargetVolatile() {
   3.381 +        return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
   3.382 +    }
   3.383 +    /*package-private*/
   3.384 +    void setTargetVolatile(MethodHandle newTarget) {
   3.385 +        unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
   3.386 +        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
   3.387 +    }
   3.388  }
     4.1 --- a/src/share/classes/java/dyn/ClassValue.java	Tue Dec 21 15:27:55 2010 -0800
     4.2 +++ b/src/share/classes/java/dyn/ClassValue.java	Tue Dec 21 18:45:45 2010 -0800
     4.3 @@ -28,44 +28,78 @@
     4.4  import java.util.WeakHashMap;
     4.5  import java.util.concurrent.atomic.AtomicInteger;
     4.6  import java.util.concurrent.atomic.AtomicReference;
     4.7 +import java.lang.reflect.UndeclaredThrowableException;
     4.8  
     4.9  /**
    4.10   * Lazily associate a computed value with (potentially) every class.
    4.11   * @author John Rose, JSR 292 EG
    4.12   */
    4.13 -public abstract class ClassValue<T> {
    4.14 +public class ClassValue<T> {
    4.15      /**
    4.16       * Compute the given class's derived value for this {@code ClassValue}.
    4.17       * <p>
    4.18       * This method will be invoked within the first thread that accesses
    4.19 -     * the value with the {@link #get}.
    4.20 +     * the value with the {@link #get get} method.
    4.21       * <p>
    4.22       * Normally, this method is invoked at most once per class,
    4.23 -     * but it may be invoked again in case of subsequent invocations
    4.24 -     * of {@link #remove} followed by {@link #get}.
    4.25 +     * but it may be invoked again if there has been a call to
    4.26 +     * {@link #remove remove}.
    4.27 +     * <p>
    4.28 +     * If there is no override from a subclass, this method returns
    4.29 +     * the result of applying the {@code ClassValue}'s {@code computeValue}
    4.30 +     * method handle, which was supplied at construction time.
    4.31       *
    4.32 -     * @return the computed value for this thread-local
    4.33 +     * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
    4.34 +     * @throws UndeclaredThrowableException if the {@code computeValue} method handle invocation throws something other than a {@code RuntimeException} or {@code Error}
    4.35 +     * @throws UnsupportedOperationException if the {@code computeValue} method handle is null (subclasses must override)
    4.36       */
    4.37 -    protected abstract T computeValue(Class<?> type);
    4.38 +    protected T computeValue(Class<?> type) {
    4.39 +        if (computeValue == null)
    4.40 +            return null;
    4.41 +        try {
    4.42 +            return (T) (Object) computeValue.invokeGeneric(type);
    4.43 +        } catch (Throwable ex) {
    4.44 +            if (ex instanceof Error)             throw (Error) ex;
    4.45 +            if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
    4.46 +            throw new UndeclaredThrowableException(ex);
    4.47 +        }
    4.48 +    }
    4.49 +
    4.50 +    private final MethodHandle computeValue;
    4.51  
    4.52      /**
    4.53       * Creates a new class value.
    4.54 +     * Subclasses which use this constructor must override
    4.55 +     * the {@link #computeValue computeValue} method,
    4.56 +     * since the default {@code computeValue} method requires a method handle,
    4.57 +     * which this constructor does not provide.
    4.58       */
    4.59      protected ClassValue() {
    4.60 +        this.computeValue = null;
    4.61 +    }
    4.62 +
    4.63 +    /**
    4.64 +     * Creates a new class value, whose {@link #computeValue computeValue} method
    4.65 +     * will return the result of {@code computeValue.invokeGeneric(type)}.
    4.66 +     * @throws NullPointerException  if the method handle parameter is null
    4.67 +     */
    4.68 +    public ClassValue(MethodHandle computeValue) {
    4.69 +        computeValue.getClass();  // trigger NPE if null
    4.70 +        this.computeValue = computeValue;
    4.71      }
    4.72  
    4.73      /**
    4.74       * Returns the value for the given class.
    4.75       * If no value has yet been computed, it is obtained by
    4.76 -     * by an invocation of the {@link #computeValue} method.
    4.77 +     * by an invocation of the {@link #computeValue computeValue} method.
    4.78       * <p>
    4.79       * The actual installation of the value on the class
    4.80 -     * is performed while the class's synchronization lock
    4.81 -     * is held.  At that point, if racing threads have
    4.82 +     * is performed atomically.
    4.83 +     * At that point, if racing threads have
    4.84       * computed values, one is chosen, and returned to
    4.85       * all the racing threads.
    4.86       *
    4.87 -     * @return the current thread's value of this thread-local
    4.88 +     * @return the current value associated with this {@code ClassValue}, for the given class or interface
    4.89       */
    4.90      public T get(Class<?> type) {
    4.91          ClassValueMap map = getMap(type);
    4.92 @@ -81,9 +115,16 @@
    4.93      /**
    4.94       * Removes the associated value for the given class.
    4.95       * If this value is subsequently {@linkplain #get read} for the same class,
    4.96 -     * its value will be reinitialized by invoking its {@link #computeValue} method.
    4.97 +     * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
    4.98       * This may result in an additional invocation of the
    4.99 -     * {@code computeValue} method for the given class.
   4.100 +     * {@code computeValue computeValue} method for the given class.
   4.101 +     * <p>
   4.102 +     * If racing threads perform a combination of {@code get} and {@code remove} calls,
   4.103 +     * the calls are serialized.
   4.104 +     * A value produced by a call to {@code computeValue} will be discarded, if
   4.105 +     * the corresponding {@code get} call was followed by a {@code remove} call
   4.106 +     * before the {@code computeValue} could complete.
   4.107 +     * In such a case, the {@code get} call will re-invoke {@code computeValue}.
   4.108       */
   4.109      public void remove(Class<?> type) {
   4.110          ClassValueMap map = getMap(type);
   4.111 @@ -118,6 +159,7 @@
   4.112              // Warm up the table with a null entry.
   4.113              map.preInitializeEntry(this);
   4.114          }
   4.115 +        STORE_BARRIER.lazySet(0);
   4.116          // All stores pending from table expansion are completed.
   4.117          synchronized (map) {
   4.118              value = (T) map.initializeEntry(this, value);
     5.1 --- a/src/share/classes/java/dyn/ConstantCallSite.java	Tue Dec 21 15:27:55 2010 -0800
     5.2 +++ b/src/share/classes/java/dyn/ConstantCallSite.java	Tue Dec 21 18:45:45 2010 -0800
     5.3 @@ -27,17 +27,21 @@
     5.4  
     5.5  /**
     5.6   * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
     5.7 - * The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
     5.8 - * to invalidate the instruction as a whole.
     5.9 + * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
    5.10 + * bound to the call site's target.
    5.11   * @author John Rose, JSR 292 EG
    5.12   */
    5.13  public class ConstantCallSite extends CallSite {
    5.14 -    /** Create a call site with a permanent target. */
    5.15 +    /** Create a call site with a permanent target.
    5.16 +     * @throws NullPointerException if the proposed target is null
    5.17 +     */
    5.18      public ConstantCallSite(MethodHandle target) {
    5.19          super(target);
    5.20      }
    5.21 -    /** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
    5.22 +    /**
    5.23 +     * Throw an {@link UnsupportedOperationException}, because this kind of call site cannot change its target.
    5.24 +     */
    5.25      @Override public final void setTarget(MethodHandle ignore) {
    5.26 -        throw new IllegalArgumentException("ConstantCallSite");
    5.27 +        throw new UnsupportedOperationException("ConstantCallSite");
    5.28      }
    5.29  }
     6.1 --- a/src/share/classes/java/dyn/InvokeDynamic.java	Tue Dec 21 15:27:55 2010 -0800
     6.2 +++ b/src/share/classes/java/dyn/InvokeDynamic.java	Tue Dec 21 18:45:45 2010 -0800
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -26,55 +26,8 @@
    6.11  package java.dyn;
    6.12  
    6.13  /**
    6.14 - * {@code InvokeDynamic} is a class with neither methods nor instances,
    6.15 - * which serves only as a syntactic marker in Java source code for
    6.16 - * an {@code invokedynamic} instruction.
    6.17 - * (See <a href="package-summary.html#jvm_mods">the package information</a> for specifics on this instruction.)
    6.18 - * <p>
    6.19 - * The {@code invokedynamic} instruction is incomplete without a target method.
    6.20 - * The target method is a property of the reified {@linkplain CallSite call site object}
    6.21 - * which is linked to each active {@code invokedynamic} instruction.
    6.22 - * The call site object is initially produced by a
    6.23 - * {@linkplain BootstrapMethod bootstrap method}
    6.24 - * associated with the class whose bytecodes include the dynamic call site.
    6.25 - * <p>
    6.26 - * The type {@code InvokeDynamic} has no particular meaning as a
    6.27 - * class or interface supertype, or an object type; it can never be instantiated.
    6.28 - * Logically, it denotes a source of all dynamically typed methods.
    6.29 - * It may be viewed as a pure syntactic marker of static calls.
    6.30 - * It may be imported for ease of use.
    6.31 - * <p>
    6.32 - * Here are some examples:
    6.33 -<blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
    6.34 -&#064;BootstrapMethod(value=Here.class, name="bootstrapDynamic")
    6.35 -static void example() throws Throwable {
    6.36 -    Object x; String s; int i;
    6.37 -    x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
    6.38 -    s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
    6.39 -    InvokeDynamic.cogito(); // cogito()V
    6.40 -    i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
    6.41 + * This is a place-holder class.  Some HotSpot implementations need to see it.
    6.42 + */
    6.43 +final class InvokeDynamic {
    6.44 +    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
    6.45  }
    6.46 -static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
    6.47 -</pre></blockquote>
    6.48 - * Each of the above calls generates a single invokedynamic instruction
    6.49 - * with the name-and-type descriptors indicated in the comments.
    6.50 - * <p>
    6.51 - * The argument types are taken directly from the actual arguments,
    6.52 - * while the return type corresponds to the target of the assignment.
    6.53 - * (Currently, the return type must be given as a false type parameter.
    6.54 - * This type parameter is an irregular use of the generic type syntax,
    6.55 - * and is likely to change in favor of a convention based on target typing.)
    6.56 - * <p>
    6.57 - * The final example uses a special syntax for uttering non-Java names.
    6.58 - * Any name legal to the JVM may be given between the double quotes.
    6.59 - * <p>
    6.60 - * None of these calls is complete without a bootstrap method,
    6.61 - * which must be declared for the enclosing class or method.
    6.62 - * @author John Rose, JSR 292 EG
    6.63 - */
    6.64 -@MethodHandle.PolymorphicSignature
    6.65 -public final class InvokeDynamic {
    6.66 -    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
    6.67 -
    6.68 -    // no statically defined static methods
    6.69 -}
     7.1 --- a/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Tue Dec 21 15:27:55 2010 -0800
     7.2 +++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Tue Dec 21 18:45:45 2010 -0800
     7.3 @@ -67,4 +67,16 @@
     7.4      public InvokeDynamicBootstrapError(String s, Throwable cause) {
     7.5          super(s, cause);
     7.6      }
     7.7 +
     7.8 +    /**
     7.9 +     * Constructs a {@code InvokeDynamicBootstrapError} with the specified
    7.10 +     * cause.
    7.11 +     *
    7.12 +     * @param cause the cause, may be {@code null}.
    7.13 +     */
    7.14 +    public InvokeDynamicBootstrapError(Throwable cause) {
    7.15 +        // cf. Throwable(Throwable cause) constructor.
    7.16 +        super(cause == null ? null : cause.toString());
    7.17 +        initCause(cause);
    7.18 +    }
    7.19  }
     8.1 --- a/src/share/classes/java/dyn/Linkage.java	Tue Dec 21 15:27:55 2010 -0800
     8.2 +++ b/src/share/classes/java/dyn/Linkage.java	Tue Dec 21 18:45:45 2010 -0800
     8.3 @@ -29,15 +29,16 @@
     8.4  import java.util.WeakHashMap;
     8.5  import sun.dyn.Access;
     8.6  import sun.dyn.MethodHandleImpl;
     8.7 +import sun.dyn.util.VerifyAccess;
     8.8  import sun.reflect.Reflection;
     8.9 -import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
    8.10  import static sun.dyn.MemberName.newIllegalArgumentException;
    8.11  
    8.12  /**
    8.13 - * This class consists exclusively of static methods that control
    8.14 - * the linkage of {@code invokedynamic} instructions, and specifically
    8.15 - * their reification as {@link CallSite} objects.
    8.16 + * <em>CLASS WILL BE REMOVED FOR PFD:</em>
    8.17 + * Static routines for controlling invokedynamic behavior.
    8.18 + * Replaced by non-static APIs.
    8.19   * @author John Rose, JSR 292 EG
    8.20 + * @deprecated This class will be removed in the Public Final Draft.
    8.21   */
    8.22  public class Linkage {
    8.23      private static final Access IMPL_TOKEN = Access.getToken();
    8.24 @@ -45,68 +46,24 @@
    8.25      private Linkage() {}  // do not instantiate
    8.26  
    8.27      /**
    8.28 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    8.29 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
    8.30       * Register a <em>bootstrap method</em> to use when linking dynamic call sites within
    8.31       * a given caller class.
    8.32 -     * <p>
    8.33 -     * A bootstrap method must be a method handle with a return type of {@link CallSite}
    8.34 -     * and the following arguments:
    8.35 -     * <ul>
    8.36 -     * <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
    8.37 -     * <li>the name of the method being invoked (a {@link String})
    8.38 -     * <li>the type of the method being invoked (a {@link MethodType})
    8.39 -     * </ul>
    8.40 -     * The bootstrap method acts as a factory method which accepts the given arguments
    8.41 -     * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
    8.42 -     * <p>
    8.43 -     * The registration must take place exactly once, either before the class has begun
    8.44 -     * being initialized, or from within the class's static initializer.
    8.45 -     * Registration will fail with an exception if any of the following conditions hold:
    8.46 -     * <ul>
    8.47 -     * <li>The immediate caller of this method is in a different package than the given caller class,
    8.48 -     *     and there is a security manager, and its {@code checkPermission} call throws
    8.49 -     *     when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
    8.50 -     * <li>The given caller class already has a bootstrap method registered.
    8.51 -     * <li>The given caller class is already fully initialized.
    8.52 -     * <li>The given caller class is in the process of initialization, in another thread.
    8.53 -     * </ul>
    8.54 -     * Because of these rules, a class may install its own bootstrap method in
    8.55 -     * a static initializer.
    8.56 -     * @param callerClass a class that may have {@code invokedynamic} sites
    8.57 -     * @param bootstrapMethod the method to use to bootstrap all such sites
    8.58 -     * @exception IllegalArgumentException if the class argument is null or
    8.59 -     *            a primitive class, or if the bootstrap method is the wrong type
    8.60 -     * @exception IllegalStateException if the class already has a bootstrap
    8.61 -     *            method, or if the its static initializer has already run
    8.62 -     *            or is already running in another thread
    8.63 -     * @exception SecurityException if there is a security manager installed,
    8.64 -     *            and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
    8.65 -     * @deprecated Use @{@link BootstrapMethod} annotations instead
    8.66 +     * @deprecated Use @{@link BootstrapMethod} annotations instead.
    8.67       */
    8.68      public static
    8.69      void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
    8.70          Class callc = Reflection.getCallerClass(2);
    8.71 -        checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
    8.72 -        checkBSM(bootstrapMethod);
    8.73 +        if (callc != null && !VerifyAccess.isSamePackage(callerClass, callc))
    8.74 +            throw new IllegalArgumentException("cannot set bootstrap method on "+callerClass);
    8.75          MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
    8.76      }
    8.77  
    8.78 -    static private void checkBSM(MethodHandle mh) {
    8.79 -        if (mh == null)  throw newIllegalArgumentException("null bootstrap method");
    8.80 -        if (mh.type() == BOOTSTRAP_METHOD_TYPE)  return;
    8.81 -        throw new WrongMethodTypeException(mh.toString());
    8.82 -    }
    8.83 -
    8.84      /**
    8.85 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    8.86 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
    8.87       * Simplified version of {@code registerBootstrapMethod} for self-registration,
    8.88       * to be called from a static initializer.
    8.89 -     * Finds a static method of the required type in the
    8.90 -     * given runtime class, and installs it on the caller class.
    8.91 -     * @throws NoSuchMethodException if there is no such method
    8.92 -     * @throws IllegalStateException if the caller class's static initializer
    8.93 -     *         has already run, or is already running in another thread
    8.94 -     * @deprecated Use @{@link BootstrapMethod} annotations instead
    8.95 +     * @deprecated Use @{@link BootstrapMethod} annotations instead.
    8.96       */
    8.97      public static
    8.98      void registerBootstrapMethod(Class<?> runtime, String name) {
    8.99 @@ -115,15 +72,9 @@
   8.100      }
   8.101  
   8.102      /**
   8.103 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   8.104 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
   8.105       * Simplified version of {@code registerBootstrapMethod} for self-registration,
   8.106 -     * to be called from a static initializer.
   8.107 -     * Finds a static method of the required type in the
   8.108 -     * caller class itself, and installs it on the caller class.
   8.109 -     * @throws IllegalArgumentException if there is no such method
   8.110 -     * @throws IllegalStateException if the caller class's static initializer
   8.111 -     *         has already run, or is already running in another thread
   8.112 -     * @deprecated Use @{@link BootstrapMethod} annotations instead
   8.113 +     * @deprecated Use @{@link BootstrapMethod} annotations instead.
   8.114       */
   8.115      public static
   8.116      void registerBootstrapMethod(String name) {
   8.117 @@ -140,82 +91,33 @@
   8.118          } catch (NoAccessException ex) {
   8.119              throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
   8.120          }
   8.121 -        checkBSM(bootstrapMethod);
   8.122          MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
   8.123      }
   8.124  
   8.125 -    /**
   8.126 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   8.127 -     * Report the bootstrap method registered for a given caller class.
   8.128 -     * Returns null if the class has never yet registered a bootstrap method.
   8.129 -     * Only callers privileged to set the bootstrap method may inquire
   8.130 -     * about it, because a bootstrap method is potentially a back-door entry
   8.131 -     * point into its class.
   8.132 -     * @exception IllegalArgumentException if the argument is null or
   8.133 -     *            a primitive class
   8.134 -     * @exception SecurityException if there is a security manager installed,
   8.135 -     *            and the immediate caller of this method is not in the same
   8.136 -     *            package as the caller class
   8.137 -     *            and a {@link LinkagePermission} check fails for "getBootstrapMethod"
   8.138 -     * @deprecated
   8.139 -     */
   8.140 -    public static
   8.141 -    MethodHandle getBootstrapMethod(Class callerClass) {
   8.142 -        Class callc = Reflection.getCallerClass(2);
   8.143 -        checkBootstrapPrivilege(callc, callerClass, "getBootstrapMethod");
   8.144 -        return MethodHandleImpl.getBootstrap(IMPL_TOKEN, callerClass);
   8.145 -    }
   8.146 -
   8.147 -    /**
   8.148 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   8.149 -     * The type of any bootstrap method is a three-argument method
   8.150 -     * {@code (Class, String, MethodType)} returning a {@code CallSite}.
   8.151 -     */
   8.152 -    public static final MethodType BOOTSTRAP_METHOD_TYPE
   8.153 +    private static final MethodType BOOTSTRAP_METHOD_TYPE
   8.154              = MethodType.methodType(CallSite.class,
   8.155                                      Class.class, String.class, MethodType.class);
   8.156  
   8.157      /**
   8.158 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   8.159 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
   8.160       * Invalidate all <code>invokedynamic</code> call sites everywhere.
   8.161 -     * <p>
   8.162 -     * When this method returns, every <code>invokedynamic</code> instruction
   8.163 -     * will invoke its bootstrap method on next call.
   8.164 -     * <p>
   8.165 -     * It is unspecified whether call sites already known to the Java
   8.166 -     * code will continue to be associated with <code>invokedynamic</code>
   8.167 -     * instructions.  If any call site is still so associated, its
   8.168 -     * {@link CallSite#getTarget()} method is guaranteed to return null
   8.169 -     * the invalidation operation completes.
   8.170 -     * <p>
   8.171 -     * Invalidation operations are likely to be slow.  Use them sparingly.
   8.172 +     * @deprecated Use {@linkplain CallSite#setTarget call site target setting}
   8.173 +     * and {@link VolatileCallSite#invalidateAll call site invalidation} instead.
   8.174       */
   8.175      public static
   8.176      Object invalidateAll() {
   8.177 -        SecurityManager security = System.getSecurityManager();
   8.178 -        if (security != null) {
   8.179 -            security.checkPermission(new LinkagePermission("invalidateAll"));
   8.180 -        }
   8.181 -        throw new UnsupportedOperationException("NYI");
   8.182 +        throw new UnsupportedOperationException();
   8.183      }
   8.184  
   8.185      /**
   8.186 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   8.187 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
   8.188       * Invalidate all {@code invokedynamic} call sites in the bytecodes
   8.189       * of any methods of the given class.
   8.190 -     * <p>
   8.191 -     * When this method returns, every matching <code>invokedynamic</code>
   8.192 -     * instruction will invoke its bootstrap method on next call.
   8.193 -     * <p>
   8.194 -     * For additional semantics of call site invalidation,
   8.195 -     * see {@link #invalidateAll()}.
   8.196 +     * @deprecated Use {@linkplain CallSite#setTarget call site target setting}
   8.197 +     * and {@link VolatileCallSite#invalidateAll call site invalidation} instead.
   8.198       */
   8.199      public static
   8.200      Object invalidateCallerClass(Class<?> callerClass) {
   8.201 -        SecurityManager security = System.getSecurityManager();
   8.202 -        if (security != null) {
   8.203 -            security.checkPermission(new LinkagePermission("invalidateAll", callerClass));
   8.204 -        }
   8.205 -        throw new UnsupportedOperationException("NYI");
   8.206 +        throw new UnsupportedOperationException();
   8.207      }
   8.208  }
     9.1 --- a/src/share/classes/java/dyn/LinkagePermission.java	Tue Dec 21 15:27:55 2010 -0800
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,104 +0,0 @@
     9.4 -/*
     9.5 - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
    9.11 - * particular file as subject to the "Classpath" exception as provided
    9.12 - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.25 - * or visit www.oracle.com if you need additional information or have any
    9.26 - * 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 - * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    9.38 - * This class is for managing runtime permission checking for
    9.39 - * operations performed by methods in the {@link Linkage} class.
    9.40 - * Like a {@link RuntimePermission}, on which it is modeled,
    9.41 - * a {@code LinkagePermission} contains a target name but
    9.42 - * no actions list; you either have the named permission
    9.43 - * or you don't.
    9.44 - * <p>
    9.45 - * The following table lists all the possible {@code LinkagePermission} target names,
    9.46 - * and for each provides a description of what the permission allows
    9.47 - * and a discussion of the risks of granting code the permission.
    9.48 - * <p>
    9.49 - *
    9.50 - * <table border=1 cellpadding=5 summary="permission target name,
    9.51 - *  what the target allows,and associated risks">
    9.52 - * <tr>
    9.53 - * <th>Permission Target Name</th>
    9.54 - * <th>What the Permission Allows</th>
    9.55 - * <th>Risks of Allowing this Permission</th>
    9.56 - * </tr>
    9.57 - *
    9.58 - * <tr>
    9.59 - *   <td>invalidateAll</td>
    9.60 - *   <td>Force the relinking of invokedynamic call sites everywhere.</td>
    9.61 - *   <td>This could allow an attacker to slow down the system,
    9.62 - *       or perhaps expose timing bugs in a dynamic language implementations,
    9.63 - *       by forcing redundant relinking operations.</td>
    9.64 - * </tr>
    9.65 - *
    9.66 - *
    9.67 - * <tr>
    9.68 - *   <td>invalidateCallerClass.{class name}</td>
    9.69 - *   <td>Force the relinking of invokedynamic call sites in the given class.</td>
    9.70 - *   <td>See {@code invalidateAll}.</td>
    9.71 - * </tr>
    9.72 - * </table>
    9.73 - * <p>ISSUE: Is this still needed?
    9.74 - *
    9.75 - * @see java.lang.RuntimePermission
    9.76 - * @see java.lang.SecurityManager
    9.77 - *
    9.78 - * @author John Rose, JSR 292 EG
    9.79 - */
    9.80 -
    9.81 -public final class LinkagePermission extends BasicPermission {
    9.82 -    private static final long serialVersionUID = 292L;
    9.83 -
    9.84 -    /**
    9.85 -     * Create a new LinkagePermission with the given name.
    9.86 -     * The name is the symbolic name of the LinkagePermission, such as
    9.87 -     * "invalidateCallerClass.*", etc. An asterisk
    9.88 -     * may appear at the end of the name, following a ".", or by itself, to
    9.89 -     * signify a wildcard match.
    9.90 -     *
    9.91 -     * @param name the name of the LinkagePermission
    9.92 -     */
    9.93 -    public LinkagePermission(String name) {
    9.94 -        super(name);
    9.95 -    }
    9.96 -
    9.97 -    /**
    9.98 -     * Create a new LinkagePermission with the given name on the given class.
    9.99 -     * Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
   9.100 -     *
   9.101 -     * @param name the name of the LinkagePermission
   9.102 -     * @param clazz the class affected by the permission
   9.103 -     */
   9.104 -    public LinkagePermission(String name, Class<?> clazz) {
   9.105 -        super(name + "." + clazz.getName());
   9.106 -    }
   9.107 -}
    10.1 --- a/src/share/classes/java/dyn/MethodHandle.java	Tue Dec 21 15:27:55 2010 -0800
    10.2 +++ b/src/share/classes/java/dyn/MethodHandle.java	Tue Dec 21 18:45:45 2010 -0800
    10.3 @@ -37,20 +37,29 @@
    10.4   * A method handle is a typed, directly executable reference to a method,
    10.5   * constructor, field, or similar low-level operation, with optional
    10.6   * transformations of arguments or return values.
    10.7 - * (These transformations include conversion, insertion, deletion,
    10.8 - * substitution.  See the methods of this class and of {@link MethodHandles}.)
    10.9 + * These transformations are quite general, and include such patterns as
   10.10 + * {@linkplain #asType conversion},
   10.11 + * {@linkplain #bindTo insertion},
   10.12 + * {@linkplain java.dyn.MethodHandles#dropArguments deletion},
   10.13 + * and {@linkplain java.dyn.MethodHandles#filterArguments substitution}.
   10.14 + * <p>
   10.15 + * <em>Note: The super-class of MethodHandle is Object.
   10.16 + *     Any other super-class visible in the Reference Implementation
   10.17 + *     will be removed before the Proposed Final Draft.
   10.18 + *     Also, the final version will not include any public or
   10.19 + *     protected constructors.</em>
   10.20   * <p>
   10.21   * Method handles are strongly typed according to signature.
   10.22   * They are not distinguished by method name or enclosing class.
   10.23   * A method handle must be invoked under a signature which matches
   10.24 - * the method handle's own {@link MethodType method type}.
   10.25 + * the method handle's own {@linkplain MethodType method type}.
   10.26   * <p>
   10.27 - * Every method handle confesses its type via the {@code type} accessor.
   10.28 + * Every method handle reports its type via the {@link #type type} accessor.
   10.29   * The structure of this type is a series of classes, one of which is
   10.30   * the return type of the method (or {@code void.class} if none).
   10.31   * <p>
   10.32   * Every method handle appears as an object containing a method named
   10.33 - * {@code invoke}, whose signature exactly matches
   10.34 + * {@link #invokeExact invokeExact}, whose signature exactly matches
   10.35   * the method handle's type.
   10.36   * A Java method call expression, which compiles to an
   10.37   * {@code invokevirtual} instruction,
   10.38 @@ -61,15 +70,29 @@
   10.39   * (The type is specified in the {@code invokevirtual} instruction,
   10.40   * via a {@code CONSTANT_NameAndType} constant pool entry.)
   10.41   * The call looks within the receiver object for a method
   10.42 - * named {@code invoke} of the intended method type.
   10.43 + * named {@code invokeExact} of the intended method type.
   10.44   * The call fails with a {@link WrongMethodTypeException}
   10.45 - * if the method does not exist, even if there is an {@code invoke}
   10.46 + * if the method does not exist, even if there is an {@code invokeExact}
   10.47   * method of a closely similar signature.
   10.48   * As with other kinds
   10.49   * of methods in the JVM, signature matching during method linkage
   10.50   * is exact, and does not allow for language-level implicit conversions
   10.51   * such as {@code String} to {@code Object} or {@code short} to {@code int}.
   10.52   * <p>
   10.53 + * Each individual method handle also contains a method named
   10.54 + * {@link #invokeGeneric invokeGeneric}, whose type is the same
   10.55 + * as {@code invokeExact}, and is therefore also reported by
   10.56 + * the {@link #type type} accessor.
   10.57 + * A call to {@code invokeGeneric} works the same as a call to
   10.58 + * {@code invokeExact}, if the signature specified by the caller
   10.59 + * exactly matches the method handle's own type.
   10.60 + * If there is a type mismatch, {@code invokeGeneric} attempts
   10.61 + * to adjust the type of the target method handle
   10.62 + * (as if by a call to {@link #asType asType})
   10.63 + * to obtain an exactly invokable target.
   10.64 + * This allows a more powerful negotiation of method type
   10.65 + * between caller and callee.
   10.66 + * <p>
   10.67   * A method handle is an unrestricted capability to call a method.
   10.68   * A method handle can be formed on a non-public method by a class
   10.69   * that has access to that method; the resulting handle can be used
   10.70 @@ -77,31 +100,47 @@
   10.71   * checking is performed when the method handle is created, not
   10.72   * (as in reflection) every time it is called.  Handles to non-public
   10.73   * methods, or in non-public classes, should generally be kept secret.
   10.74 - * They should not be passed to untrusted code.
   10.75 + * They should not be passed to untrusted code unless their use from
   10.76 + * the untrusted code would be harmless.
   10.77   * <p>
   10.78 - * Bytecode in an extended JVM can directly call a method handle's
   10.79 - * {@code invoke} from an {@code invokevirtual} instruction.
   10.80 + * Bytecode in the JVM can directly call a method handle's
   10.81 + * {@code invokeExact} method from an {@code invokevirtual} instruction.
   10.82   * The receiver class type must be {@code MethodHandle} and the method name
   10.83 - * must be {@code invoke}.  The signature of the invocation
   10.84 + * must be {@code invokeExact}.  The signature of the invocation
   10.85   * (after resolving symbolic type names) must exactly match the method type
   10.86   * of the target method.
   10.87 + * Similarly, bytecode can directly call a method handle's {@code invokeGeneric}
   10.88 + * method.  The signature of the invocation (after resolving symbolic type names)
   10.89 + * must either exactly match the method type or be a valid argument to
   10.90 + * the target's {@link #asType asType} method.
   10.91   * <p>
   10.92 - * Every {@code invoke} method always throws {@link Exception},
   10.93 + * Every {@code invokeExact} and {@code invokeGeneric} method always
   10.94 + * throws {@link java.lang.Throwable Throwable},
   10.95   * which is to say that there is no static restriction on what a method handle
   10.96   * can throw.  Since the JVM does not distinguish between checked
   10.97   * and unchecked exceptions (other than by their class, of course),
   10.98   * there is no particular effect on bytecode shape from ascribing
   10.99   * checked exceptions to method handle invocations.  But in Java source
  10.100   * code, methods which perform method handle calls must either explicitly
  10.101 - * throw {@code Exception}, or else must catch all checked exceptions locally.
  10.102 + * throw {@code java.lang.Throwable Throwable}, or else must catch all
  10.103 + * throwables locally, rethrowing only those which are legal in the context,
  10.104 + * and wrapping ones which are illegal.
  10.105   * <p>
  10.106 - * Bytecode in an extended JVM can directly obtain a method handle
  10.107 + * Bytecode in the JVM can directly obtain a method handle
  10.108   * for any accessible method from a {@code ldc} instruction
  10.109 - * which refers to a {@code CONSTANT_Methodref} or
  10.110 - * {@code CONSTANT_InterfaceMethodref} constant pool entry.
  10.111 + * which refers to a {@code CONSTANT_MethodHandle} constant pool entry.
  10.112 + * (Each such entry refers directly to a {@code CONSTANT_Methodref},
  10.113 + * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
  10.114 + * constant pool entry.
  10.115 + * For more details, see the <a href="package-summary.html#mhcon">package summary</a>.)
  10.116   * <p>
  10.117 - * All JVMs can also use a reflective API called {@code MethodHandles}
  10.118 + * Java code can also use a reflective API called
  10.119 + * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup}
  10.120   * for creating and calling method handles.
  10.121 + * For example, a static method handle can be obtained
  10.122 + * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}.
  10.123 + * There are also bridge methods from Core Reflection API objects,
  10.124 + * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.ureflect}.
  10.125   * <p>
  10.126   * A method reference may refer either to a static or non-static method.
  10.127   * In the non-static case, the method handle type includes an explicit
  10.128 @@ -128,10 +167,10 @@
  10.129  mt = MethodType.methodType(String.class, char.class, char.class);
  10.130  mh = lookup.findVirtual(String.class, "replace", mt);
  10.131  // (Ljava/lang/String;CC)Ljava/lang/String;
  10.132 -s = mh.&lt;String&gt;invokeExact("daddy",'d','n');
  10.133 +s = (String) mh.invokeExact("daddy",'d','n');
  10.134  assert(s.equals("nanny"));
  10.135  // weakly typed invocation (using MHs.invoke)
  10.136 -s = (String) mh.invokeVarargs("sappy", 'p', 'v');
  10.137 +s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
  10.138  assert(s.equals("savvy"));
  10.139  // mt is {Object[] =&gt; List}
  10.140  mt = MethodType.methodType(java.util.List.class, Object[].class);
  10.141 @@ -147,14 +186,22 @@
  10.142  mt = MethodType.methodType(int.class);
  10.143  mh = lookup.findVirtual(java.util.List.class, "size", mt);
  10.144  // (Ljava/util/List;)I
  10.145 -i = mh.&lt;int&gt;invokeExact(java.util.Arrays.asList(1,2,3));
  10.146 +i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
  10.147  assert(i == 3);
  10.148 +mt = MethodType.methodType(void.class, String.class);
  10.149 +mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
  10.150 +mh.invokeExact(System.out, "Hello, world.");
  10.151 +// (Ljava/io/PrintStream;Ljava/lang/String;)V
  10.152   * </pre></blockquote>
  10.153   * Each of the above calls generates a single invokevirtual instruction
  10.154   * with the name {@code invoke} and the type descriptors indicated in the comments.
  10.155   * The argument types are taken directly from the actual arguments,
  10.156 - * while the return type is taken from the type parameter.
  10.157 - * (This type parameter may be a primitive, and it defaults to {@code Object}.)
  10.158 + * while the return type is taken from the cast immediately applied to the call.
  10.159 + * This cast may be to a primitive.
  10.160 + * If it is missing, the type defaults to {@code Object} if the call
  10.161 + * occurs in a context which uses the return value.
  10.162 + * If the call occurs as a statement, a cast is impossible,
  10.163 + * and there is no return type; the call is {@code void}.
  10.164   * <p>
  10.165   * <em>A note on generic typing:</em>  Method handles do not represent
  10.166   * their function types in terms of Java parameterized (generic) types,
  10.167 @@ -162,7 +209,7 @@
  10.168   * Java types.
  10.169   * <ol>
  10.170   * <li>Method types range over all possible arities,
  10.171 - * from no arguments to an arbitrary number of arguments.
  10.172 + * from no arguments to up to 255 of arguments (a limit imposed by the JVM).
  10.173   * Generics are not variadic, and so cannot represent this.</li>
  10.174   * <li>Method types can specify arguments of primitive types,
  10.175   * which Java generic types cannot range over.</li>
  10.176 @@ -180,6 +227,19 @@
  10.177   * fields, methods, and constructors can be represented directly
  10.178   * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
  10.179   * Loading such a constant causes the component classes of its type to be loaded as necessary.
  10.180 + * <p>
  10.181 + * Method handles cannot be subclassed by the user.
  10.182 + * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
  10.183 + * which may be visible via the {@code java.lang.Object#getClass Object.getClass}
  10.184 + * operation.  The programmer should not draw conclusions about a method handle
  10.185 + * from its specific class, as the method handle class hierarchy (if any)
  10.186 + * may change from time to time or across implementations from different vendors.
  10.187 + * <p>
  10.188 + * With respect to the Java Memory Model, any method handle will behave
  10.189 + * as if all of its fields are final variables.  This means that any method
  10.190 + * handle made visible to the application will always be fully formed.
  10.191 + * This is true even if the method handle is published through a shared
  10.192 + * variables in a data race.
  10.193   *
  10.194   * @see MethodType
  10.195   * @see MethodHandles
  10.196 @@ -189,7 +249,6 @@
  10.197          // Note: This is an implementation inheritance hack, and will be removed
  10.198          // with a JVM change which moves the required hidden state onto this class.
  10.199          extends MethodHandleImpl
  10.200 -        implements MethodHandleProvider
  10.201  {
  10.202      private static Access IMPL_TOKEN = Access.getToken();
  10.203  
  10.204 @@ -208,7 +267,7 @@
  10.205  
  10.206      /**
  10.207       * Report the type of this method handle.
  10.208 -     * Every invocation of this method handle must exactly match this type.
  10.209 +     * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
  10.210       * @return the method handle type
  10.211       */
  10.212      public final MethodType type() {
  10.213 @@ -216,12 +275,16 @@
  10.214      }
  10.215  
  10.216      /**
  10.217 -     * The constructor for MethodHandle may only be called by privileged code.
  10.218 -     * Subclasses may be in other packages, but must possess
  10.219 -     * a token which they obtained from MH with a security check.
  10.220 -     * @param token non-null object which proves access permission
  10.221 -     * @param type type (permanently assigned) of the new method handle
  10.222 +     * <em>CONSTRUCTOR WILL BE REMOVED FOR PFD:</em>
  10.223 +     * Temporary constructor in early versions of the Reference Implementation.
  10.224 +     * Method handle inheritance (if any) will be contained completely within
  10.225 +     * the {@code java.dyn} package.
  10.226       */
  10.227 +    // The constructor for MethodHandle may only be called by privileged code.
  10.228 +    // Subclasses may be in other packages, but must possess
  10.229 +    // a token which they obtained from MH with a security check.
  10.230 +    // @param token non-null object which proves access permission
  10.231 +    // @param type type (permanently assigned) of the new method handle
  10.232      protected MethodHandle(Access token, MethodType type) {
  10.233          super(token);
  10.234          Access.check(token);
  10.235 @@ -243,92 +306,116 @@
  10.236          });
  10.237      }
  10.238  
  10.239 -    /** The string of a direct method handle is the simple name of its target method.
  10.240 -     * The string of an adapter or bound method handle is the string of its
  10.241 -     * target method handle.
  10.242 -     * The string of a Java method handle is the string of its entry point method,
  10.243 -     * unless the Java method handle overrides the toString method.
  10.244 +    /**
  10.245 +     * Returns a string representation of the method handle,
  10.246 +     * starting with the string {@code "MethodHandle"} and
  10.247 +     * ending with the string representation of the method handle's type.
  10.248 +     * In other words, this method returns a string equal to the value of:
  10.249 +     * <blockquote><pre>
  10.250 +     * "MethodHandle" + type().toString()
  10.251 +     * </pre></blockquote>
  10.252 +     * <p>
  10.253 +     * Note:  Future releases of this API may add further information
  10.254 +     * to the string representation.
  10.255 +     * Therefore, the present syntax should not be parsed by applications.
  10.256 +     *
  10.257 +     * @return a string representation of the method handle
  10.258       */
  10.259      @Override
  10.260      public String toString() {
  10.261          return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
  10.262      }
  10.263  
  10.264 -    //// This is the "Method Handle Kernel API" discussed at the JVM Language Summit, 9/2009.
  10.265 -    //// Implementations here currently delegate to statics in MethodHandles.  Some of those statics
  10.266 -    //// will be deprecated.  Others will be kept as "algorithms" to supply degrees of freedom
  10.267 -    //// not present in the Kernel API.
  10.268 +    /**
  10.269 +     * Invoke the method handle, allowing any caller signature, but requiring an exact signature match.
  10.270 +     * The signature at the call site of {@code invokeExact} must
  10.271 +     * exactly match this method handle's {@link #type type}.
  10.272 +     * No conversions are allowed on arguments or return values.
  10.273 +     * @throws WrongMethodTypeException if the target's type is not identical with the caller's type signature
  10.274 +     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
  10.275 +     */
  10.276 +    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
  10.277  
  10.278      /**
  10.279 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.280 -     * Invoke the method handle, allowing any caller signature, but requiring an exact signature match.
  10.281 -     * The signature at the call site of {@code invokeExact} must
  10.282 -     * exactly match this method handle's {@code type}.
  10.283 -     * No conversions are allowed on arguments or return values.
  10.284 +     * Invoke the method handle, allowing any caller signature,
  10.285 +     * and optionally performing conversions for arguments and return types.
  10.286 +     * <p>
  10.287 +     * If the call site signature exactly matches this method handle's {@link #type type},
  10.288 +     * the call proceeds as if by {@link #invokeExact invokeExact}.
  10.289 +     * <p>
  10.290 +     * Otherwise, the call proceeds as if this method handle were first
  10.291 +     * adjusted by calling {@link #asType asType} to adjust this method handle
  10.292 +     * to the required type, and then the call proceeds as if by
  10.293 +     * {@link #invokeExact invokeExact} on the adjusted method handle.
  10.294 +     * <p>
  10.295 +     * There is no guarantee that the {@code asType} call is actually made.
  10.296 +     * If the JVM can predict the results of making the call, it may perform
  10.297 +     * adaptations directly on the caller's arguments,
  10.298 +     * and call the target method handle according to its own exact type.
  10.299 +     * <p>
  10.300 +     * If the method handle is equipped with a
  10.301 +     * {@linkplain #withTypeHandler type handler}, the handler must produce
  10.302 +     * an entry point of the call site's exact type.
  10.303 +     * Otherwise, the signature at the call site of {@code invokeGeneric} must
  10.304 +     * be a valid argument to the standard {@code asType} method.
  10.305 +     * In particular, the caller must specify the same argument arity
  10.306 +     * as the callee's type.
  10.307 +     * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type signature
  10.308 +     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
  10.309       */
  10.310 -    public final native @PolymorphicSignature <R,A> R invokeExact(A... args) throws Throwable;
  10.311 -
  10.312 -    // FIXME: remove this transitional form
  10.313 -    /** @deprecated transitional form defined in EDR but removed in PFD */
  10.314 -    public final native @PolymorphicSignature <R,A> R invoke(A... args) throws Throwable;
  10.315 +    public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
  10.316  
  10.317      /**
  10.318 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.319 -     * Invoke the method handle, allowing any caller signature,
  10.320 -     * and performing simple conversions for arguments and return types.
  10.321 -     * The signature at the call site of {@code invokeGeneric} must
  10.322 -     * have the same arity as this method handle's {@code type}.
  10.323 -     * <p>
  10.324 -     * If the call site signature exactly matches this method handle's {@code type},
  10.325 -     * the call proceeds as if by {@link #invokeExact}.
  10.326 -     * <p>
  10.327 -     * Otherwise, the call proceeds as if this method handle were first
  10.328 -     * adjusted by calling {@link #asType} to adjust this method handle
  10.329 -     * to the required type, and then the call proceeds as if by
  10.330 -     * {@link #invokeExact} on the adjusted method handle.
  10.331 -     */
  10.332 -    public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable;
  10.333 -
  10.334 -    // ?? public final native @PolymorphicSignature <R,A,V> R invokeVarargs(A args, V[] varargs) throws Throwable;
  10.335 -
  10.336 -    /**
  10.337 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.338       * Perform a varargs invocation, passing the arguments in the given array
  10.339 -     * to the method handle, as if via {@link #invokeGeneric} from a call site
  10.340 +     * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
  10.341       * which mentions only the type {@code Object}, and whose arity is the length
  10.342       * of the argument array.
  10.343       * <p>
  10.344 -     * The length of the arguments array must equal the parameter count
  10.345 -     * of the target's type.
  10.346 -     * The arguments array is spread into separate arguments.
  10.347 +     * Specifically, execution proceeds as if by the following steps,
  10.348 +     * although the methods are not guaranteed to be called if the JVM
  10.349 +     * can predict their effects.
  10.350 +     * <ul>
  10.351 +     * <li>Determine the length of the argument array as {@code N}.
  10.352 +     *     For a null reference, {@code N=0}. </li>
  10.353 +     * <li>Determine the generic type {@code TN} of {@code N} arguments as
  10.354 +     *     as {@code TN=MethodType.genericMethodType(N)}.</li>
  10.355 +     * <li>Force the original target method handle {@code MH0} to the
  10.356 +     *     required type, as {@code MH1 = MH0.asType(TN)}. </li>
  10.357 +     * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
  10.358 +     * <li>Invoke the type-adjusted method handle on the unpacked arguments:
  10.359 +     *     MH1.invokeExact(A0, ...). </li>
  10.360 +     * <li>Take the return value as an {@code Object} reference. </li>
  10.361 +     * </ul>
  10.362       * <p>
  10.363 -     * In order to match the type of the target, the following argument
  10.364 +     * Because of the action of the {@code asType} step, the following argument
  10.365       * conversions are applied as necessary:
  10.366       * <ul>
  10.367       * <li>reference casting
  10.368       * <li>unboxing
  10.369 +     * <li>widening primitive conversions
  10.370       * </ul>
  10.371 -     * The following conversions are not applied:
  10.372 -     * <ul>
  10.373 -     * <li>primitive conversions (e.g., {@code byte} to {@code int}
  10.374 -     * <li>varargs conversions other than the initial spread
  10.375 -     * <li>any application-specific conversions (e.g., string to number)
  10.376 -     * </ul>
  10.377 +     * <p>
  10.378       * The result returned by the call is boxed if it is a primitive,
  10.379       * or forced to null if the return type is void.
  10.380       * <p>
  10.381       * This call is equivalent to the following code:
  10.382       * <p><blockquote><pre>
  10.383 -     *   MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
  10.384 -     *   Object result = invoker.invokeExact(this, arguments);
  10.385 +     * MethodHandle invoker = MethodHandles.varargsInvoker(this.type(), 0);
  10.386 +     * Object result = invoker.invokeExact(this, arguments);
  10.387       * </pre></blockquote>
  10.388       * @param arguments the arguments to pass to the target
  10.389       * @return the result returned by the target
  10.390 -     * @see MethodHandles#genericInvoker
  10.391 +     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the arguments
  10.392 +     * @throws Throwable anything thrown by the target method invocation
  10.393 +     * @see MethodHandles#varargsInvoker
  10.394       */
  10.395 -    public final Object invokeVarargs(Object... arguments) throws Throwable {
  10.396 +    public final Object invokeWithArguments(Object... arguments) throws Throwable {
  10.397          int argc = arguments == null ? 0 : arguments.length;
  10.398          MethodType type = type();
  10.399 +        if (type.parameterCount() != argc) {
  10.400 +            // simulate invokeGeneric
  10.401 +            return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
  10.402 +        }
  10.403          if (argc <= 10) {
  10.404              MethodHandle invoker = MethodHandles.invokers(type).genericInvoker();
  10.405              switch (argc) {
  10.406 @@ -372,99 +459,70 @@
  10.407          MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0);
  10.408          return invoker.invokeExact(this, arguments);
  10.409      }
  10.410 -    /** Equivalent to {@code invokeVarargs(arguments.toArray())}. */
  10.411 +    /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
  10.412 +    public final Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
  10.413 +        return invokeWithArguments(arguments.toArray());
  10.414 +    }
  10.415 +    @Deprecated
  10.416 +    public final Object invokeVarargs(Object... arguments) throws Throwable {
  10.417 +        return invokeWithArguments(arguments);
  10.418 +    }
  10.419 +    @Deprecated
  10.420      public final Object invokeVarargs(java.util.List<?> arguments) throws Throwable {
  10.421 -        return invokeVarargs(arguments.toArray());
  10.422 +        return invokeWithArguments(arguments.toArray());
  10.423      }
  10.424  
  10.425 -    /*  --- this is intentionally NOT a javadoc yet ---
  10.426 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.427 +    /**
  10.428       * Produce an adapter method handle which adapts the type of the
  10.429 -     * current method handle to a new type by pairwise argument conversion.
  10.430 -     * The original type and new type must have the same number of arguments.
  10.431 -     * The resulting method handle is guaranteed to confess a type
  10.432 +     * current method handle to a new type
  10.433 +     * The resulting method handle is guaranteed to report a type
  10.434       * which is equal to the desired new type.
  10.435       * <p>
  10.436       * If the original type and new type are equal, returns {@code this}.
  10.437       * <p>
  10.438 -     * The following conversions are applied as needed both to
  10.439 -     * arguments and return types.  Let T0 and T1 be the differing
  10.440 -     * new and old parameter types (or old and new return types)
  10.441 -     * for corresponding values passed by the new and old method types.
  10.442 -     * Given those types T0, T1, one of the following conversions is applied
  10.443 -     * if possible:
  10.444 -     * <ul>
  10.445 -     * <li>If T0 and T1 are references, and T1 is not an interface type,
  10.446 -     *     then a cast to T1 is applied.
  10.447 -     *     (The types do not need to be related in any particular way.)
  10.448 -     * <li>If T0 and T1 are references, and T1 is an interface type,
  10.449 -     *     then the value of type T0 is passed as a T1 without a cast.
  10.450 -     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
  10.451 -     * <li>If T0 and T1 are primitives, then a Java casting
  10.452 -     *     conversion (JLS 5.5) is applied, if one exists.
  10.453 -     * <li>If T0 and T1 are primitives and one is boolean,
  10.454 -     *     the boolean is treated as a one-bit unsigned integer.
  10.455 -     *     (This treatment follows the usage of the bytecode verifier.)
  10.456 -     *     A conversion from another primitive type behaves as if
  10.457 -     *     it first converts to byte, and then masks all but the low bit.
  10.458 -     * <li>If T0 is a primitive and T1 a reference, a boxing
  10.459 -     *     conversion is applied if one exists, possibly followed by
  10.460 -     *     an reference conversion to a superclass.
  10.461 -     *     T1 must be a wrapper class or a supertype of one.
  10.462 -     *     If T1 is a wrapper class, T0 is converted if necessary
  10.463 -     *     to T1's primitive type by one of the preceding conversions.
  10.464 -     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
  10.465 -     * <li>If T0 is a reference and T1 a primitive, an unboxing
  10.466 -     *     conversion is applied if one exists, possibly preceded by
  10.467 -     *     a reference conversion to a wrapper class.
  10.468 -     *     T0 must be a wrapper class or a supertype of one.
  10.469 -     *     If T0 is a wrapper class, its primitive value is converted
  10.470 -     *     if necessary to T1 by one of the preceding conversions.
  10.471 -     *     Otherwise, T0 is converted directly to the wrapper type for T1,
  10.472 -     *     which is then unboxed.
  10.473 -     * <li>If the return type T1 is void, any returned value is discarded
  10.474 -     * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
  10.475 -     * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
  10.476 -     * </ul>
  10.477 +     * This method provides the crucial behavioral difference between
  10.478 +     * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.  The two methods
  10.479 +     * perform the same steps when the caller's type descriptor is identical
  10.480 +     * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric}
  10.481 +     * also calls {@code asType} (or some internal equivalent) in order
  10.482 +     * to match up the caller's and callee's types.
  10.483       * <p>
  10.484 -     */
  10.485 -    /**
  10.486 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.487 -     * Produce an adapter method handle which adapts the type of the
  10.488 -     * current method handle to a new type by pairwise argument conversion.
  10.489 -     * The original type and new type must have the same number of arguments.
  10.490 -     * The resulting method handle is guaranteed to confess a type
  10.491 -     * which is equal to the desired new type.
  10.492 +     * This method is equivalent to {@link MethodHandles#convertArguments convertArguments},
  10.493 +     * except for method handles produced by {@link #withTypeHandler withTypeHandler},
  10.494 +     * in which case the specified type handler is used for calls to {@code asType}.
  10.495       * <p>
  10.496 -     * If the original type and new type are equal, returns {@code this}.
  10.497 -     * <p>
  10.498 -     * This method is equivalent to {@link MethodHandles#convertArguments}.
  10.499 +     * Note that the default behavior of {@code asType} only performs
  10.500 +     * pairwise argument conversion and return value conversion.
  10.501 +     * Because of this, unless the method handle has a type handler,
  10.502 +     * the original type and new type must have the same number of arguments.
  10.503 +     *
  10.504       * @param newType the expected type of the new method handle
  10.505       * @return a method handle which delegates to {@code this} after performing
  10.506       *           any necessary argument conversions, and arranges for any
  10.507       *           necessary return value conversions
  10.508 -     * @throws IllegalArgumentException if the conversion cannot be made
  10.509 +     * @throws WrongMethodTypeException if the conversion cannot be made
  10.510       * @see MethodHandles#convertArguments
  10.511       */
  10.512 -    public final MethodHandle asType(MethodType newType) {
  10.513 +    public MethodHandle asType(MethodType newType) {
  10.514          return MethodHandles.convertArguments(this, newType);
  10.515      }
  10.516  
  10.517      /**
  10.518 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.519       * Produce a method handle which adapts, as its <i>target</i>,
  10.520       * the current method handle.  The type of the adapter will be
  10.521 -     * the same as the type of the target, except that all but the first
  10.522 -     * {@code keepPosArgs} parameters of the target's type are replaced
  10.523 -     * by a single array parameter of type {@code Object[]}.
  10.524 -     * Thus, if {@code keepPosArgs} is zero, the adapter will take all
  10.525 -     * arguments in a single object array.
  10.526 +     * the same as the type of the target, except that the final
  10.527 +     * {@code arrayLength} parameters of the target's type are replaced
  10.528 +     * by a single array parameter of type {@code arrayType}.
  10.529 +     * <p>
  10.530 +     * If the array element type differs from any of the corresponding
  10.531 +     * argument types on original target,
  10.532 +     * the original target is adapted to take the array elements directly,
  10.533 +     * as if by a call to {@link #asType asType}.
  10.534       * <p>
  10.535       * When called, the adapter replaces a trailing array argument
  10.536       * by the array's elements, each as its own argument to the target.
  10.537       * (The order of the arguments is preserved.)
  10.538       * They are converted pairwise by casting and/or unboxing
  10.539 -     * (as if by {@link MethodHandles#convertArguments})
  10.540       * to the types of the trailing parameters of the target.
  10.541       * Finally the target is called.
  10.542       * What the target eventually returns is returned unchanged by the adapter.
  10.543 @@ -473,54 +531,67 @@
  10.544       * contains exactly enough elements to provide a correct argument count
  10.545       * to the target method handle.
  10.546       * (The array may also be null when zero elements are required.)
  10.547 -     * @param keepPosArgs the number of leading positional arguments to preserve
  10.548 -     * @return a new method handle which spreads its final argument,
  10.549 +     * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
  10.550 +     * @param arrayLength the number of arguments to spread from an incoming array argument
  10.551 +     * @return a new method handle which spreads its final array argument,
  10.552       *         before calling the original method handle
  10.553 +     * @throws IllegalArgumentException if {@code arrayType} is not an array type
  10.554       * @throws IllegalArgumentException if target does not have at least
  10.555 -     *         {@code keepPosArgs} parameter types
  10.556 +     *         {@code arrayLength} parameter types
  10.557 +     * @throws WrongMethodTypeException if the implied {@code asType} call fails
  10.558       */
  10.559 -    public final MethodHandle asSpreader(int keepPosArgs) {
  10.560 +    public final MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
  10.561 +        Class<?> arrayElement = arrayType.getComponentType();
  10.562 +        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
  10.563          MethodType oldType = type();
  10.564          int nargs = oldType.parameterCount();
  10.565 +        if (nargs < arrayLength)  throw newIllegalArgumentException("bad spread array length");
  10.566 +        int keepPosArgs = nargs - arrayLength;
  10.567          MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
  10.568 -        newType = newType.insertParameterTypes(keepPosArgs, Object[].class);
  10.569 +        newType = newType.insertParameterTypes(keepPosArgs, arrayType);
  10.570          return MethodHandles.spreadArguments(this, newType);
  10.571      }
  10.572  
  10.573      /**
  10.574 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.575       * Produce a method handle which adapts, as its <i>target</i>,
  10.576       * the current method handle.  The type of the adapter will be
  10.577       * the same as the type of the target, except that a single trailing
  10.578 -     * array parameter of type {@code Object[]} is replaced by
  10.579 -     * {@code spreadArrayArgs} parameters of type {@code Object}.
  10.580 +     * parameter (usually of type {@code arrayType}) is replaced by
  10.581 +     * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
  10.582       * <p>
  10.583 -     * When called, the adapter replaces its trailing {@code spreadArrayArgs}
  10.584 -     * arguments by a single new {@code Object} array, whose elements
  10.585 +     * If the array type differs from the final argument type on original target,
  10.586 +     * the original target is adapted to take the array type directly,
  10.587 +     * as if by a call to {@link #asType asType}.
  10.588 +     * <p>
  10.589 +     * When called, the adapter replaces its trailing {@code arrayLength}
  10.590 +     * arguments by a single new array of type {@code arrayType}, whose elements
  10.591       * comprise (in order) the replaced arguments.
  10.592       * Finally the target is called.
  10.593       * What the target eventually returns is returned unchanged by the adapter.
  10.594       * <p>
  10.595 -     * (The array may also be a shared constant when {@code spreadArrayArgs} is zero.)
  10.596 -     * @param spreadArrayArgs the number of arguments to spread from the trailing array
  10.597 +     * (The array may also be a shared constant when {@code arrayLength} is zero.)
  10.598 +     * @param arrayType usually {@code Object[]}, the type of the array argument which will collect the arguments
  10.599 +     * @param arrayLength the number of arguments to collect into a new array argument
  10.600       * @return a new method handle which collects some trailing argument
  10.601       *         into an array, before calling the original method handle
  10.602 -     * @throws IllegalArgumentException if the last argument of the target
  10.603 -     *         is not {@code Object[]}
  10.604 -     * @throws IllegalArgumentException if {@code spreadArrayArgs} is not
  10.605 +     * @throws IllegalArgumentException if {@code arrayType} is not an array type
  10.606 +               or {@code arrayType} is not assignable to this method handle's trailing parameter type
  10.607 +     * @throws IllegalArgumentException if {@code arrayLength} is not
  10.608       *         a legal array size
  10.609 -     * @deprecated Provisional and unstable; use {@link MethodHandles#collectArguments}.
  10.610 +     * @throws WrongMethodTypeException if the implied {@code asType} call fails
  10.611       */
  10.612 -    public final MethodHandle asCollector(int spreadArrayArgs) {
  10.613 +    public final MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
  10.614 +        Class<?> arrayElement = arrayType.getComponentType();
  10.615 +        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
  10.616          MethodType oldType = type();
  10.617          int nargs = oldType.parameterCount();
  10.618          MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
  10.619 -        newType = newType.insertParameterTypes(nargs-1, MethodType.genericMethodType(spreadArrayArgs).parameterArray());
  10.620 +        newType = newType.insertParameterTypes(nargs-1,
  10.621 +                    java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement));
  10.622          return MethodHandles.collectArguments(this, newType);
  10.623      }
  10.624  
  10.625      /**
  10.626 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.627       * Produce a method handle which binds the given argument
  10.628       * to the current method handle as <i>target</i>.
  10.629       * The type of the bound handle will be
  10.630 @@ -541,15 +612,81 @@
  10.631       *         leading parameter type that is a reference type
  10.632       * @throws ClassCastException if {@code x} cannot be converted
  10.633       *         to the leading parameter type of the target
  10.634 -     * @deprecated Provisional and unstable; use {@link MethodHandles#insertArguments}.
  10.635 +     * @see MethodHandles#insertArguments
  10.636       */
  10.637      public final MethodHandle bindTo(Object x) {
  10.638          return MethodHandles.insertArguments(this, 0, x);
  10.639      }
  10.640  
  10.641 -    /** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */
  10.642 -    public final MethodHandle asMethodHandle() { return this; }
  10.643 +    /**
  10.644 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  10.645 +     * Create a new method handle with the same type as this one,
  10.646 +     * but whose {@code asType} method invokes the given
  10.647 +     * {@code typeHandler} on this method handle,
  10.648 +     * instead of the standard {@code MethodHandles.convertArguments}.
  10.649 +     * <p>
  10.650 +     * The new method handle will have the same behavior as the
  10.651 +     * old one when invoked by {@code invokeExact}.
  10.652 +     * For {@code invokeGeneric} calls which exactly match
  10.653 +     * the method type, the two method handles will also
  10.654 +     * have the same behavior.
  10.655 +     * For other {@code invokeGeneric} calls, the {@code typeHandler}
  10.656 +     * will control the behavior of the new method handle.
  10.657 +     * <p>
  10.658 +     * Thus, a method handle with an {@code asType} handler can
  10.659 +     * be configured to accept more than one arity of {@code invokeGeneric}
  10.660 +     * call, and potentially every possible arity.
  10.661 +     * It can also be configured to supply default values for
  10.662 +     * optional arguments, when the caller does not specify them.
  10.663 +     * <p>
  10.664 +     * The given method handle must take two arguments and return
  10.665 +     * one result.  The result it returns must be a method handle
  10.666 +     * of exactly the requested type.  If the result returned by
  10.667 +     * the target is null, a {@link NullPointerException} is thrown,
  10.668 +     * else if the type of the target does not exactly match
  10.669 +     * the requested type, a {@link WrongMethodTypeException} is thrown.
  10.670 +     * <p>
  10.671 +     * A method handle's type handler is not guaranteed to be called every
  10.672 +     * time its {@code asType} or {@code invokeGeneric} method is called.
  10.673 +     * If the implementation is faced is able to prove that an equivalent
  10.674 +     * type handler call has already occurred (on the same two arguments),
  10.675 +     * it may substitute the result of that previous invocation, without
  10.676 +     * making a new invocation.  Thus, type handlers should not (in general)
  10.677 +     * perform significant side effects.
  10.678 +     * <p>
  10.679 +     * Therefore, the type handler is invoked as if by this code:
  10.680 +     * <blockquote><pre>
  10.681 +     * MethodHandle target = this;      // original method handle
  10.682 +     * MethodHandle adapter = ...;      // adapted method handle
  10.683 +     * MethodType requestedType = ...;  // argument to asType()
  10.684 +     * if (type().equals(requestedType))
  10.685 +     *    return adapter;
  10.686 +     * MethodHandle result = (MethodHandle)
  10.687 +     *    typeHandler.invokeGeneric(target, requestedType);
  10.688 +     * if (!result.type().equals(requestedType))
  10.689 +     *    throw new WrongMethodTypeException();
  10.690 +     * return result;
  10.691 +     * </pre></blockquote>
  10.692 +     * <p>
  10.693 +     * For example, here is a list-making variable-arity method handle:
  10.694 +     * <blockquote><pre>
  10.695 +MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList());
  10.696 +MethodHandle asList = lookup()
  10.697 +  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
  10.698 +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) {
  10.699 +  return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType);
  10.700 +}
  10.701 +MethodHandle collectingTypeHandler = lookup()
  10.702 +  .findStatic(lookup().lookupClass(), "collectingTypeHandler",
  10.703 +     methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
  10.704 +MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler);
  10.705  
  10.706 -    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */
  10.707 -    public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); }
  10.708 +assertEquals("[]", makeAnyList.invokeGeneric().toString());
  10.709 +assertEquals("[1]", makeAnyList.invokeGeneric(1).toString());
  10.710 +assertEquals("[two, too]", makeAnyList.invokeGeneric("two", "too").toString());
  10.711 +     * <pre><blockquote>
  10.712 +     */
  10.713 +    public MethodHandle withTypeHandler(MethodHandle typeHandler) {
  10.714 +        return MethodHandles.withTypeHandler(this, typeHandler);
  10.715 +    }
  10.716  }
    11.1 --- a/src/share/classes/java/dyn/MethodHandleProvider.java	Tue Dec 21 15:27:55 2010 -0800
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,80 +0,0 @@
    11.4 -/*
    11.5 - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   11.11 - * particular file as subject to the "Classpath" exception as provided
   11.12 - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.25 - * or visit www.oracle.com if you need additional information or have any
   11.26 - * questions.
   11.27 - */
   11.28 -
   11.29 -package java.dyn;
   11.30 -
   11.31 -/**
   11.32 - * An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
   11.33 - * There are many function-like objects in various Java APIs.
   11.34 - * This interface provides a standard way for such function-like objects to be bound
   11.35 - * to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
   11.36 - * <p>
   11.37 - * The type {@link MethodHandle} is a concrete class whose implementation
   11.38 - * hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
   11.39 - * It cannot also serve as a base type for user-defined functional APIs.
   11.40 - * For this reason, {@code MethodHandle} cannot be subclassed to add new
   11.41 - * behavior to method handles.  But this interface can be used to provide
   11.42 - * a link between a user-defined function and the {@code invokedynamic}
   11.43 - * instruction and the method handle API.
   11.44 - */
   11.45 -public interface MethodHandleProvider {
   11.46 -    /** Produce a method handle which will serve as a behavioral proxy for the current object.
   11.47 -     *  The type and invocation behavior of the proxy method handle are user-defined,
   11.48 -     *  and should have some relation to the intended meaning of the original object itself.
   11.49 -     *  <p>
   11.50 -     *  The current object may have a changeable behavior.
   11.51 -     *  For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
   11.52 -     *  In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
   11.53 -     *  a method handle whose behavior may diverge from that of the current object.
   11.54 -     *  Rather, the returned method handle must stably and permanently access
   11.55 -     *  the behavior of the current object, even if that behavior is changeable.
   11.56 -     *  <p>
   11.57 -     *  The reference identity of the proxy method handle is not guaranteed to
   11.58 -     *  have any particular relation to the reference identity of the object.
   11.59 -     *  In particular, several objects with the same intended meaning could
   11.60 -     *  share a common method handle, or the same object could return different
   11.61 -     *  method handles at different times.  In the latter case, the different
   11.62 -     *  method handles should have the same type and invocation behavior,
   11.63 -     *  and be usable from any thread at any time.
   11.64 -     *  In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
   11.65 -     *  call site, the proxy method handle extracted at the time of binding
   11.66 -     *  will be used for an unlimited time, until the call site is rebound.
   11.67 -     *  <p>
   11.68 -     *  The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
   11.69 -     *  for this method simply returns {@code this}.
   11.70 -     */
   11.71 -    public MethodHandle asMethodHandle();
   11.72 -
   11.73 -    /** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
   11.74 -     *  As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
   11.75 -     *  proxy method handle is user-defined.  But the type must be the given type,
   11.76 -     *  or else a {@link WrongMethodTypeException} must be thrown.
   11.77 -     *  <p>
   11.78 -     *  If the current object somehow represents a variadic or overloaded behavior,
   11.79 -     *  the method handle returned for a given type might represent only a subset of
   11.80 -     *  the current object's repertoire of behaviors, which correspond to that type.
   11.81 -     */
   11.82 -    public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException;
   11.83 -}
    12.1 --- a/src/share/classes/java/dyn/MethodHandles.java	Tue Dec 21 15:27:55 2010 -0800
    12.2 +++ b/src/share/classes/java/dyn/MethodHandles.java	Tue Dec 21 18:45:45 2010 -0800
    12.3 @@ -29,6 +29,7 @@
    12.4  import sun.dyn.Access;
    12.5  import sun.dyn.MemberName;
    12.6  import sun.dyn.MethodHandleImpl;
    12.7 +import sun.dyn.util.ValueConversions;
    12.8  import sun.dyn.util.VerifyAccess;
    12.9  import sun.dyn.util.Wrapper;
   12.10  import java.util.List;
   12.11 @@ -135,28 +136,58 @@
   12.12       * In general, the conditions under which a method handle may be
   12.13       * created for a method {@code M} are exactly as restrictive as the conditions
   12.14       * under which the lookup class could have compiled a call to {@code M}.
   12.15 -     * This rule is applied even if the Java compiler might have created
   12.16 +     * <p>
   12.17 +     * In some cases, this access is obtained by the Java compiler by creating
   12.18       * an wrapper method to access a private method of another class
   12.19       * in the same top-level declaration.
   12.20 -     * For example, a lookup object created for a nested class {@code C.D}
   12.21 +     * For example, a nested class {@code C.D}
   12.22       * can access private members within other related classes such as
   12.23 -     * {@code C}, {@code C.D.E}, or {@code C.B}.
   12.24 +     * {@code C}, {@code C.D.E}, or {@code C.B},
   12.25 +     * but the Java compiler may need to generate wrapper methods in
   12.26 +     * those related classes.  In such cases, a {@code Lookup} object on
   12.27 +     * {@code C.E} would be unable to those private members.
   12.28 +     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
   12.29 +     * which can transform a lookup on {@code C.E} into one on any of those other
   12.30 +     * classes, without special elevation of privilege.
   12.31       */
   12.32      public static final
   12.33      class Lookup {
   12.34          /** The class on behalf of whom the lookup is being performed. */
   12.35          private final Class<?> lookupClass;
   12.36  
   12.37 -        /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */
   12.38 +        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
   12.39          private final int allowedModes;
   12.40  
   12.41 -        private static final int
   12.42 -            PUBLIC    = Modifier.PUBLIC,
   12.43 -            PACKAGE   = Modifier.STATIC,
   12.44 -            PROTECTED = Modifier.PROTECTED,
   12.45 -            PRIVATE   = Modifier.PRIVATE,
   12.46 -            ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
   12.47 -            TRUSTED   = -1;
   12.48 +        /** A single-bit mask representing {@code public} access,
   12.49 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
   12.50 +         *  The value, {@code 0x01}, happens to be the same as the value of the
   12.51 +         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
   12.52 +         */
   12.53 +        public static final int PUBLIC = Modifier.PUBLIC;
   12.54 +
   12.55 +        /** A single-bit mask representing {@code private} access,
   12.56 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
   12.57 +         *  The value, {@code 0x02}, happens to be the same as the value of the
   12.58 +         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
   12.59 +         */
   12.60 +        public static final int PRIVATE = Modifier.PRIVATE;
   12.61 +
   12.62 +        /** A single-bit mask representing {@code protected} access,
   12.63 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
   12.64 +         *  The value, {@code 0x04}, happens to be the same as the value of the
   12.65 +         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
   12.66 +         */
   12.67 +        public static final int PROTECTED = Modifier.PROTECTED;
   12.68 +
   12.69 +        /** A single-bit mask representing {@code package} access (default access),
   12.70 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
   12.71 +         *  The value is {@code 0x08}, which does not correspond meaningfully to
   12.72 +         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
   12.73 +         */
   12.74 +        public static final int PACKAGE = Modifier.STATIC;
   12.75 +
   12.76 +        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
   12.77 +        private static final int TRUSTED   = -1;
   12.78  
   12.79          private static int fixmods(int mods) {
   12.80              mods &= (ALL_MODES - PACKAGE);
   12.81 @@ -181,13 +212,21 @@
   12.82          }
   12.83  
   12.84          /** Which types of members can this lookup object produce?
   12.85 -         *  The result is a bit-mask of the {@link Modifier} bits
   12.86 -         *  {@linkplain Modifier#PUBLIC PUBLIC (0x01)},
   12.87 -         *  {@linkplain Modifier#PROTECTED PROTECTED (0x02)},
   12.88 -         *  {@linkplain Modifier#PRIVATE PRIVATE (0x04)},
   12.89 -         *  and {@linkplain Modifier#STATIC STATIC (0x08)}.
   12.90 -         *  The modifier bit {@code STATIC} stands in for the package protection mode,
   12.91 -         *  which does not have an explicit modifier bit.
   12.92 +         *  The result is a bit-mask of the bits
   12.93 +         *  {@linkplain #PUBLIC PUBLIC (0x01)},
   12.94 +         *  {@linkplain #PRIVATE PRIVATE (0x02)},
   12.95 +         *  {@linkplain #PROTECTED PROTECTED (0x04)},
   12.96 +         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
   12.97 +         *  <p>
   12.98 +         *  A freshly-created lookup object
   12.99 +         *  on the {@linkplain java.dyn.MethodHandles#lookup() caller's class}
  12.100 +         *  has all possible bits set, since the caller class can access all its own members.
  12.101 +         *  A lookup object on a new lookup class
  12.102 +         *  {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object}
  12.103 +         *  may have some mode bits set to zero.
  12.104 +         *  The purpose of this is to restrict access via the new lookup object,
  12.105 +         *  so that it can access only names which can be reached by the original
  12.106 +         *  lookup object, and also by the new lookup class.
  12.107           */
  12.108          public int lookupModes() {
  12.109              return allowedModes & ALL_MODES;
  12.110 @@ -220,18 +259,21 @@
  12.111          /**
  12.112           * Create a lookup on the specified new lookup class.
  12.113           * The resulting object will report the specified
  12.114 -         * class as its own {@link #lookupClass}.
  12.115 +         * class as its own {@link #lookupClass lookupClass}.
  12.116           * <p>
  12.117           * However, the resulting {@code Lookup} object is guaranteed
  12.118           * to have no more access capabilities than the original.
  12.119 -         * In particular:<ul>
  12.120 +         * In particular, access capabilities can be lost as follows:<ul>
  12.121           * <li>If the new lookup class differs from the old one,
  12.122           * protected members will not be accessible by virtue of inheritance.
  12.123 +         * (Protected members may continue to be accessible because of package sharing.)
  12.124           * <li>If the new lookup class is in a different package
  12.125           * than the old one, protected and default (package) members will not be accessible.
  12.126           * <li>If the new lookup class is not within the same package member
  12.127           * as the old one, private members will not be accessible.
  12.128 -         * <li>In all cases, public members will continue to be accessible.
  12.129 +         * <li>If the new lookup class is not accessible to the old lookup class,
  12.130 +         * then no members, not even public members, will be accessible.
  12.131 +         * (In all other cases, public members will continue to be accessible.)
  12.132           * </ul>
  12.133           */
  12.134          public Lookup in(Class<?> requestedLookupClass) {
  12.135 @@ -245,10 +287,17 @@
  12.136                  && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
  12.137                  newModes &= ~(PACKAGE|PRIVATE);
  12.138              }
  12.139 +            // Allow nestmate lookups to be created without special privilege:
  12.140              if ((newModes & PRIVATE) != 0
  12.141                  && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
  12.142                  newModes &= ~PRIVATE;
  12.143              }
  12.144 +            if (newModes == PUBLIC
  12.145 +                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
  12.146 +                // The requested class it not accessible from the lookup class.
  12.147 +                // No permissions.
  12.148 +                newModes = 0;
  12.149 +            }
  12.150              checkUnprivilegedlookupClass(requestedLookupClass);
  12.151              return new Lookup(requestedLookupClass, newModes);
  12.152          }
  12.153 @@ -272,35 +321,43 @@
  12.154                  throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
  12.155          }
  12.156  
  12.157 -        /** Display the name of the class.
  12.158 -         *  If there are restrictions on the access permitted to this lookup,
  12.159 -         *  display those also.
  12.160 +        /**
  12.161 +         * Display the name of the class from which lookups are to be made.
  12.162 +         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
  12.163 +         * If there are restrictions on the access permitted to this lookup,
  12.164 +         * this is indicated by adding a suffix to the class name, consisting
  12.165 +         * of a slash and a keyword.  The keyword is chosen as follows:
  12.166 +         * <ul>
  12.167 +         * <li>If no access is allowed, the suffix is "/noaccess".
  12.168 +         * <li>If only public access is allowed, the suffix is "/public".
  12.169 +         * <li>If only public and package access are allowed, the suffix is "/package".
  12.170 +         * <li>If only public, package, and private access are allowed, the suffix is "/private".
  12.171 +         * </ul>
  12.172 +         * If none of the above cases apply, it is the case that full
  12.173 +         * access (public, package, private, and protected) is allowed.
  12.174 +         * In this case, no suffix is added.
  12.175 +         * This is true only of an object obtained originally from
  12.176 +         * {@link java.dyn.MethodHandles#lookup() MethodHandles.lookup}.
  12.177 +         * Objects created by {@link java.dyn.MethodHandles.Lookup#in() Lookup#in}
  12.178 +         * always have restricted access, and will display a suffix.
  12.179           */
  12.180          @Override
  12.181          public String toString() {
  12.182 -            String modestr;
  12.183              String cname = lookupClass.getName();
  12.184              switch (allowedModes) {
  12.185              case TRUSTED:
  12.186 -                return "/trusted";
  12.187 +                return "/trusted";  // internal only
  12.188              case PUBLIC:
  12.189 -                modestr = "/public";
  12.190 -                if (lookupClass == Object.class)
  12.191 -                    return modestr;
  12.192 -                break;
  12.193 +                return cname + "/public";
  12.194              case PUBLIC|PACKAGE:
  12.195                  return cname + "/package";
  12.196 -            case 0:  // should not happen
  12.197 -                return cname + "/empty";
  12.198 +            case 0:  // no privileges
  12.199 +                return cname + "/noaccess";
  12.200              case ALL_MODES:
  12.201                  return cname;
  12.202 +            default:
  12.203 +                return cname + "/private";
  12.204              }
  12.205 -            StringBuilder buf = new StringBuilder(cname);
  12.206 -            if ((allowedModes & PUBLIC) != 0)     buf.append("/public");
  12.207 -            if ((allowedModes & PACKAGE) != 0)    buf.append("/package");
  12.208 -            if ((allowedModes & PROTECTED) != 0)  buf.append("/protected");
  12.209 -            if ((allowedModes & PRIVATE) != 0)    buf.append("/private");
  12.210 -            return buf.toString();
  12.211          }
  12.212  
  12.213          // call this from an entry point method in Lookup with extraFrames=0.
  12.214 @@ -326,7 +383,6 @@
  12.215           * @param name the name of the method
  12.216           * @param type the type of the method
  12.217           * @return the desired method handle
  12.218 -         * @exception SecurityException <em>TBD</em>
  12.219           * @exception NoAccessException if the method does not exist or access checking fails
  12.220           */
  12.221          public
  12.222 @@ -342,13 +398,6 @@
  12.223           * with the receiver type (usually {@code refc}) prepended.
  12.224           * The method and all its argument types must be accessible to the lookup class.
  12.225           * <p>
  12.226 -         * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
  12.227 -         * of the receiver type, if the receiver type is not on the boot class path.
  12.228 -         * This is due to a temporary JVM limitation, in which MethodHandle
  12.229 -         * claims to be unable to access such classes.  To work around this
  12.230 -         * bug, use {@code convertArguments} to normalize the type of the leading
  12.231 -         * argument to a type on the boot class path, such as {@code Object}.)
  12.232 -         * <p>
  12.233           * When called, the handle will treat the first argument as a receiver
  12.234           * and dispatch on the receiver's type to determine which method
  12.235           * implementation to enter.
  12.236 @@ -358,7 +407,6 @@
  12.237           * @param name the name of the method
  12.238           * @param type the type of the method, with the receiver argument omitted
  12.239           * @return the desired method handle
  12.240 -         * @exception SecurityException <em>TBD</em>
  12.241           * @exception NoAccessException if the method does not exist or access checking fails
  12.242           */
  12.243          public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException {
  12.244 @@ -382,7 +430,6 @@
  12.245           * @param refc the class or interface from which the method is accessed
  12.246           * @param type the type of the method, with the receiver argument omitted, and a void return type
  12.247           * @return the desired method handle
  12.248 -         * @exception SecurityException <em>TBD</em>
  12.249           * @exception NoAccessException if the method does not exist or access checking fails
  12.250           */
  12.251          public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException {
  12.252 @@ -409,13 +456,13 @@
  12.253           * {@code invokespecial} instruction.)
  12.254           * <p>
  12.255           * If the explicitly specified caller class is not identical with the
  12.256 -         * lookup class, a security check TBD is performed.
  12.257 +         * lookup class, or if this lookup object does not have private access
  12.258 +         * privileges, the access fails.
  12.259           * @param refc the class or interface from which the method is accessed
  12.260           * @param name the name of the method (which must not be "&lt;init&gt;")
  12.261           * @param type the type of the method, with the receiver argument omitted
  12.262           * @param specialCaller the proposed calling class to perform the {@code invokespecial}
  12.263           * @return the desired method handle
  12.264 -         * @exception SecurityException <em>TBD</em>
  12.265           * @exception NoAccessException if the method does not exist or access checking fails
  12.266           */
  12.267          public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
  12.268 @@ -428,7 +475,6 @@
  12.269          }
  12.270  
  12.271          /**
  12.272 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.273           * Produce a method handle giving read access to a non-static field.
  12.274           * The type of the method handle will have a return type of the field's
  12.275           * value type.
  12.276 @@ -445,7 +491,6 @@
  12.277          }
  12.278  
  12.279          /**
  12.280 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.281           * Produce a method handle giving write access to a non-static field.
  12.282           * The type of the method handle will have a void return type.
  12.283           * The method handle will take two arguments, the instance containing
  12.284 @@ -462,7 +507,6 @@
  12.285          }
  12.286  
  12.287          /**
  12.288 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.289           * Produce a method handle giving read access to a static field.
  12.290           * The type of the method handle will have a return type of the field's
  12.291           * value type.
  12.292 @@ -478,7 +522,6 @@
  12.293          }
  12.294  
  12.295          /**
  12.296 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.297           * Produce a method handle giving write access to a static field.
  12.298           * The type of the method handle will have a void return type.
  12.299           * The method handle will take a single
  12.300 @@ -515,7 +558,6 @@
  12.301           * @param name the name of the method
  12.302           * @param type the type of the method, with the receiver argument omitted
  12.303           * @return the desired method handle
  12.304 -         * @exception SecurityException <em>TBD</em>
  12.305           * @exception NoAccessException if the method does not exist or access checking fails
  12.306           */
  12.307          public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
  12.308 @@ -530,7 +572,6 @@
  12.309          }
  12.310  
  12.311          /**
  12.312 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.313           * Make a direct method handle to <i>m</i>, if the lookup class has permission.
  12.314           * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
  12.315           * If <i>m</i> is virtual, overriding is respected on every call.
  12.316 @@ -554,7 +595,6 @@
  12.317          }
  12.318  
  12.319          /**
  12.320 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.321           * Produce a method handle for a reflected method.
  12.322           * It will bypass checks for overriding methods on the receiver,
  12.323           * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
  12.324 @@ -579,7 +619,6 @@
  12.325          }
  12.326  
  12.327          /**
  12.328 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.329           * Produce a method handle for a reflected constructor.
  12.330           * The type of the method handle will be that of the constructor,
  12.331           * with the return type changed to the declaring class.
  12.332 @@ -602,7 +641,6 @@
  12.333          }
  12.334  
  12.335          /**
  12.336 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.337           * Produce a method handle giving read access to a reflected field.
  12.338           * The type of the method handle will have a return type of the field's
  12.339           * value type.
  12.340 @@ -620,7 +658,6 @@
  12.341          }
  12.342  
  12.343          /**
  12.344 -         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.345           * Produce a method handle giving write access to a reflected field.
  12.346           * The type of the method handle will have a void return type.
  12.347           * If the field is static, the method handle will take a single
  12.348 @@ -681,7 +718,7 @@
  12.349              int allowedModes = this.allowedModes;
  12.350              if (allowedModes == TRUSTED)  return;
  12.351              int mods = m.getModifiers();
  12.352 -            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()))
  12.353 +            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
  12.354                  return;  // common case
  12.355              int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
  12.356              if ((requestedModes & allowedModes) != 0
  12.357 @@ -706,6 +743,8 @@
  12.358                  return "access to public member failed";  // (how?)
  12.359              else if (allowedModes == PUBLIC)
  12.360                  return "member is not public";
  12.361 +            else if (allowedModes == 0)
  12.362 +                return "attempted member access through a non-public class";
  12.363              if (Modifier.isPrivate(mods))
  12.364                  return "member is private";
  12.365              if (Modifier.isProtected(mods))
  12.366 @@ -713,9 +752,14 @@
  12.367              return "member is private to package";
  12.368          }
  12.369  
  12.370 +        private static final boolean ALLOW_NESTMATE_ACCESS = false;
  12.371 +
  12.372          void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
  12.373              if (allowedModes == TRUSTED)  return;
  12.374 -            if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
  12.375 +            if ((allowedModes & PRIVATE) == 0
  12.376 +                || (specialCaller != lookupClass()
  12.377 +                    && !(ALLOW_NESTMATE_ACCESS &&
  12.378 +                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
  12.379                  throw newNoAccessException("no private access for invokespecial",
  12.380                                             new MemberName(specialCaller), lookupClass());
  12.381          }
  12.382 @@ -725,7 +769,9 @@
  12.383              // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
  12.384              if (!method.isProtected() || method.isStatic()
  12.385                  || allowedModes == TRUSTED
  12.386 -                || VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))
  12.387 +                || method.getDeclaringClass() == lookupClass()
  12.388 +                || (ALLOW_NESTMATE_ACCESS &&
  12.389 +                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
  12.390                  return mh;
  12.391              else
  12.392                  return restrictReceiver(method, mh, lookupClass());
  12.393 @@ -765,7 +811,6 @@
  12.394      }
  12.395  
  12.396      /**
  12.397 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.398       * Produce a method handle giving read access to elements of an array.
  12.399       * The type of the method handle will have a return type of the array's
  12.400       * element type.  Its first argument will be the array type,
  12.401 @@ -780,7 +825,6 @@
  12.402      }
  12.403  
  12.404      /**
  12.405 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.406       * Produce a method handle giving write access to elements of an array.
  12.407       * The type of the method handle will have a void return type.
  12.408       * Its last argument will be the array's element type.
  12.409 @@ -796,25 +840,6 @@
  12.410      /// method handle invocation (reflective style)
  12.411  
  12.412      /**
  12.413 -     * @deprecated Alias for MethodHandle.invokeVarargs.
  12.414 -     */
  12.415 -    @Deprecated
  12.416 -    public static
  12.417 -    Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
  12.418 -        return target.invokeVarargs(arguments);
  12.419 -    }
  12.420 -
  12.421 -    /**
  12.422 -     * @deprecated Alias for MethodHandle.invokeVarargs.
  12.423 -     */
  12.424 -    @Deprecated
  12.425 -    public static
  12.426 -    Object invoke(MethodHandle target, Object... arguments) throws Throwable {
  12.427 -        return target.invokeVarargs(arguments);
  12.428 -    }
  12.429 -
  12.430 -    /**
  12.431 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.432       * Produce a method handle which will invoke any method handle of the
  12.433       * given type on a standard set of {@code Object} type arguments.
  12.434       * The resulting invoker will be a method handle with the following
  12.435 @@ -823,18 +848,28 @@
  12.436       * <li>a single {@code MethodHandle} target
  12.437       * <li>zero or more {@code Object} values (one for each argument in {@code type})
  12.438       * </ul>
  12.439 -     * The invoker will apply reference casts as necessary and unbox primitive arguments,
  12.440 -     * as if by {@link #convertArguments}.
  12.441 +     * <p>
  12.442 +     * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with
  12.443 +     * the indicated {@code type}.
  12.444 +     * That is, if the target is exactly of the given {@code type}, it will behave
  12.445 +     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType}
  12.446 +     * is used to convert the target to the required {@code type}.
  12.447 +     * <p>
  12.448 +     * The type of the returned invoker will not be the given {@code type}, but rather
  12.449 +     * will have all parameter and return types replaced by {@code Object}.
  12.450 +     * <p>
  12.451 +     * Before invoking its target, the invoker will apply reference casts as
  12.452 +     * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments}.
  12.453       * The return value of the invoker will be an {@code Object} reference,
  12.454       * boxing a primitive value if the original type returns a primitive,
  12.455       * and always null if the original type returns void.
  12.456       * <p>
  12.457       * This method is equivalent to the following code (though it may be more efficient):
  12.458       * <p><blockquote><pre>
  12.459 -     * MethodHandle invoker = exactInvoker(type);
  12.460 +     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
  12.461       * MethodType genericType = type.generic();
  12.462       * genericType = genericType.insertParameterType(0, MethodHandle.class);
  12.463 -     * return convertArguments(invoker, genericType);
  12.464 +     * return invoker.asType(genericType);
  12.465       * </pre></blockquote>
  12.466       * @param type the type of target methods which the invoker will apply to
  12.467       * @return a method handle suitable for invoking any method handle of the given type
  12.468 @@ -845,9 +880,8 @@
  12.469      }
  12.470  
  12.471      /**
  12.472 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.473       * Produce a method handle which will invoke any method handle of the
  12.474 -     * given type on a standard set of {@code Object} type arguments
  12.475 +     * given {@code type} on a standard set of {@code Object} type arguments
  12.476       * and a single trailing {@code Object[]} array.
  12.477       * The resulting invoker will be a method handle with the following
  12.478       * arguments:
  12.479 @@ -856,18 +890,31 @@
  12.480       * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
  12.481       * <li>an {@code Object[]} array containing more arguments
  12.482       * </ul>
  12.483 -     * The invoker will spread the varargs array, apply
  12.484 -     * reference casts as necessary, and unbox primitive arguments.
  12.485 +     * <p>
  12.486 +     * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with
  12.487 +     * the indicated {@code type}.
  12.488 +     * That is, if the target is exactly of the given {@code type}, it will behave
  12.489 +     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType}
  12.490 +     * is used to convert the target to the required {@code type}.
  12.491 +     * <p>
  12.492 +     * The type of the returned invoker will not be the given {@code type}, but rather
  12.493 +     * will have all parameter and return types replaced by {@code Object}, except for
  12.494 +     * the last parameter type, which will be the array type {@code Object[]}.
  12.495 +     * <p>
  12.496 +     * Before invoking its target, the invoker will spread the varargs array, apply
  12.497 +     * reference casts as necessary, and unbox and widen primitive arguments.
  12.498       * The return value of the invoker will be an {@code Object} reference,
  12.499       * boxing a primitive value if the original type returns a primitive,
  12.500       * and always null if the original type returns void.
  12.501       * <p>
  12.502       * This method is equivalent to the following code (though it may be more efficient):
  12.503       * <p><blockquote><pre>
  12.504 -     * MethodHandle invoker = exactInvoker(type);
  12.505 -     * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
  12.506 +     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
  12.507 +     * MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
  12.508       * vaType = vaType.insertParameterType(0, MethodHandle.class);
  12.509 -     * return spreadArguments(invoker, vaType);
  12.510 +     * int spreadArgCount = type.parameterCount - objectArgCount;
  12.511 +     * invoker = invoker.asSpreader(Object.class, spreadArgCount);
  12.512 +     * return invoker.asType(vaType);
  12.513       * </pre></blockquote>
  12.514       * @param type the desired target type
  12.515       * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
  12.516 @@ -881,7 +928,6 @@
  12.517      }
  12.518  
  12.519      /**
  12.520 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.521       * Produce a method handle which will take a invoke any method handle of the
  12.522       * given type.  The resulting invoker will have a type which is
  12.523       * exactly equal to the desired type, except that it will accept
  12.524 @@ -889,7 +935,7 @@
  12.525       * <p>
  12.526       * This method is equivalent to the following code (though it may be more efficient):
  12.527       * <p><blockquote><pre>
  12.528 -     * lookup().findVirtual(MethodHandle.class, "invoke", type);
  12.529 +     * lookup().findVirtual(MethodHandle.class, "invokeExact", type);
  12.530       * </pre></blockquote>
  12.531       * @param type the desired target type
  12.532       * @return a method handle suitable for invoking any method handle of the given type
  12.533 @@ -899,39 +945,6 @@
  12.534          return invokers(type).exactInvoker();
  12.535      }
  12.536  
  12.537 -    /**
  12.538 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.539 -     * Produce a method handle equivalent to an invokedynamic instruction
  12.540 -     * which has been linked to the given call site.
  12.541 -     * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
  12.542 -     * and {@link Lookup#findSpecial}, this completes the emulation
  12.543 -     * of the JVM's {@code invoke} instructions.
  12.544 -     * <p>This method is equivalent to the following code:
  12.545 -     * <p><blockquote><pre>
  12.546 -     * MethodHandle getTarget, invoker, result;
  12.547 -     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
  12.548 -     * invoker = exactInvoker(site.type());
  12.549 -     * result = foldArguments(invoker, getTarget)
  12.550 -     * </pre></blockquote>
  12.551 -     * @return a method handle which always invokes the call site's target
  12.552 -     */
  12.553 -    public static
  12.554 -    MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
  12.555 -        MethodHandle getCSTarget = GET_TARGET;
  12.556 -        if (getCSTarget == null) {
  12.557 -            try {
  12.558 -                GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
  12.559 -                    findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
  12.560 -            } catch (NoAccessException ex) {
  12.561 -                throw new InternalError();
  12.562 -            }
  12.563 -        }
  12.564 -        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
  12.565 -        MethodHandle invoker = exactInvoker(site.type());
  12.566 -        return foldArguments(invoker, getTarget);
  12.567 -    }
  12.568 -    private static MethodHandle GET_TARGET = null;  // link this lazily, not eagerly
  12.569 -
  12.570      static Invokers invokers(MethodType type) {
  12.571          return MethodTypeImpl.invokers(IMPL_TOKEN, type);
  12.572      }
  12.573 @@ -974,23 +987,23 @@
  12.574              if (t0.isPrimitive())
  12.575                  return Wrapper.asPrimitiveType(t1).cast(value);
  12.576              else
  12.577 -                return Wrapper.OBJECT.cast(value, t1);
  12.578 +                return Wrapper.OBJECT.convert(value, t1);
  12.579          }
  12.580          boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
  12.581          if (!prim0) {
  12.582              // check contract with caller
  12.583 -            Wrapper.OBJECT.cast(value, t0);
  12.584 +            Wrapper.OBJECT.convert(value, t0);
  12.585              if (!prim1) {
  12.586 -                return Wrapper.OBJECT.cast(value, t1);
  12.587 +                return Wrapper.OBJECT.convert(value, t1);
  12.588              }
  12.589              // convert reference to primitive by unboxing
  12.590              Wrapper w1 = Wrapper.forPrimitiveType(t1);
  12.591 -            return w1.cast(value, t1);
  12.592 +            return w1.convert(value, t1);
  12.593          }
  12.594          // check contract with caller:
  12.595          Wrapper.asWrapperType(t0).cast(value);
  12.596          Wrapper w1 = Wrapper.forPrimitiveType(t1);
  12.597 -        return w1.cast(value, t1);
  12.598 +        return w1.convert(value, t1);
  12.599      }
  12.600  
  12.601      static
  12.602 @@ -1011,7 +1024,7 @@
  12.603       * Produce a method handle which adapts the type of the
  12.604       * given method handle to a new type by pairwise argument conversion.
  12.605       * The original type and new type must have the same number of arguments.
  12.606 -     * The resulting method handle is guaranteed to confess a type
  12.607 +     * The resulting method handle is guaranteed to report a type
  12.608       * which is equal to the desired new type.
  12.609       * <p>
  12.610       * If the original type and new type are equal, returns target.
  12.611 @@ -1023,34 +1036,21 @@
  12.612       * Given those types T0, T1, one of the following conversions is applied
  12.613       * if possible:
  12.614       * <ul>
  12.615 -     * <li>If T0 and T1 are references, and T1 is not an interface type,
  12.616 -     *     then a cast to T1 is applied.
  12.617 +     * <li>If T0 and T1 are references, then a cast to T1 is applied.
  12.618       *     (The types do not need to be related in any particular way.)
  12.619 -     * <li>If T0 and T1 are references, and T1 is an interface type,
  12.620 -     *     then the value of type T0 is passed as a T1 without a cast.
  12.621 -     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
  12.622 -     * <li>If T0 and T1 are primitives, then a Java casting
  12.623 -     *     conversion (JLS 5.5) is applied, if one exists.
  12.624 -     * <li>If T0 and T1 are primitives and one is boolean,
  12.625 -     *     the boolean is treated as a one-bit unsigned integer.
  12.626 -     *     (This treatment follows the usage of the bytecode verifier.)
  12.627 -     *     A conversion from another primitive type behaves as if
  12.628 -     *     it first converts to byte, and then masks all but the low bit.
  12.629 +     * <li>If T0 and T1 are primitives, then a Java method invocation
  12.630 +     *     conversion (JLS 5.3) is applied, if one exists.
  12.631       * <li>If T0 is a primitive and T1 a reference, a boxing
  12.632       *     conversion is applied if one exists, possibly followed by
  12.633 -     *     an reference conversion to a superclass.
  12.634 +     *     a reference conversion to a superclass.
  12.635       *     T1 must be a wrapper class or a supertype of one.
  12.636 -     *     If T1 is a wrapper class, T0 is converted if necessary
  12.637 -     *     to T1's primitive type by one of the preceding conversions.
  12.638 -     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
  12.639       * <li>If T0 is a reference and T1 a primitive, an unboxing
  12.640 -     *     conversion is applied if one exists, possibly preceded by
  12.641 -     *     a reference conversion to a wrapper class.
  12.642 +     *     conversion will be applied at runtime, possibly followed
  12.643 +     *     by a Java method invocation conversion (JLS 5.3)
  12.644 +     *     on the primitive value.  (These are the widening conversions.)
  12.645       *     T0 must be a wrapper class or a supertype of one.
  12.646 -     *     If T0 is a wrapper class, its primitive value is converted
  12.647 -     *     if necessary to T1 by one of the preceding conversions.
  12.648 -     *     Otherwise, T0 is converted directly to the wrapper type for T1,
  12.649 -     *     which is then unboxed.
  12.650 +     *     (In the case where T0 is Object, these are the conversions
  12.651 +     *     allowed by java.lang.reflect.Method.invoke.)
  12.652       * <li>If the return type T1 is void, any returned value is discarded
  12.653       * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
  12.654       * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
  12.655 @@ -1060,26 +1060,109 @@
  12.656       * @return a method handle which delegates to {@code target} after performing
  12.657       *           any necessary argument conversions, and arranges for any
  12.658       *           necessary return value conversions
  12.659 -     * @throws IllegalArgumentException if the conversion cannot be made
  12.660 +     * @throws WrongMethodTypeException if the conversion cannot be made
  12.661       * @see MethodHandle#asType
  12.662 +     * @see MethodHandles#explicitCastArguments
  12.663       */
  12.664      public static
  12.665      MethodHandle convertArguments(MethodHandle target, MethodType newType) {
  12.666          MethodType oldType = target.type();
  12.667          if (oldType.equals(newType))
  12.668              return target;
  12.669 -        MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
  12.670 -                                                 newType, oldType, null);
  12.671 +        MethodHandle res = null;
  12.672 +        try {
  12.673 +            res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
  12.674 +                                                    newType, oldType, null);
  12.675 +        } catch (IllegalArgumentException ex) {
  12.676 +        }
  12.677          if (res == null)
  12.678 -            throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
  12.679 +            throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
  12.680          return res;
  12.681      }
  12.682  
  12.683      /**
  12.684 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.685 +     * Produce a method handle which adapts the type of the
  12.686 +     * given method handle to a new type by pairwise argument conversion.
  12.687 +     * The original type and new type must have the same number of arguments.
  12.688 +     * The resulting method handle is guaranteed to report a type
  12.689 +     * which is equal to the desired new type.
  12.690 +     * <p>
  12.691 +     * If the original type and new type are equal, returns target.
  12.692 +     * <p>
  12.693 +     * The same conversions are allowed as for {@link #convertArguments convertArguments},
  12.694 +     * and some additional conversions are also applied if those conversions fail.
  12.695 +     * Given types T0, T1, one of the following conversions is applied
  12.696 +     * in addition, if the conversions specified for {@code convertArguments}
  12.697 +     * would be insufficient:
  12.698 +     * <ul>
  12.699 +     * <li>If T0 and T1 are references, and T1 is an interface type,
  12.700 +     *     then the value of type T0 is passed as a T1 without a cast.
  12.701 +     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
  12.702 +     * <li>If T0 and T1 are primitives and one is boolean,
  12.703 +     *     the boolean is treated as a one-bit unsigned integer.
  12.704 +     *     (This treatment follows the usage of the bytecode verifier.)
  12.705 +     *     A conversion from another primitive type behaves as if
  12.706 +     *     it first converts to byte, and then masks all but the low bit.
  12.707 +     * <li>If a primitive value would be converted by {@code convertArguments}
  12.708 +     *     using Java method invocation conversion (JLS 5.3),
  12.709 +     *     Java casting conversion (JLS 5.5) may be used also.
  12.710 +     *     This allows primitives to be narrowed as well as widened.
  12.711 +     * </ul>
  12.712 +     * @param target the method handle to invoke after arguments are retyped
  12.713 +     * @param newType the expected type of the new method handle
  12.714 +     * @return a method handle which delegates to {@code target} after performing
  12.715 +     *           any necessary argument conversions, and arranges for any
  12.716 +     *           necessary return value conversions
  12.717 +     * @throws WrongMethodTypeException if the conversion cannot be made
  12.718 +     * @see MethodHandle#asType
  12.719 +     * @see MethodHandles#convertArguments
  12.720 +     */
  12.721 +    public static
  12.722 +    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
  12.723 +        return convertArguments(target, newType);  // FIXME!
  12.724 +    }
  12.725 +
  12.726 +    /*
  12.727 +      FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
  12.728 +
  12.729 +      Both converters arrange for their method handles to convert arguments
  12.730 +      and return values.  The conversion rules are the same for arguments
  12.731 +      and return values, and depend only on source and target types, S and
  12.732 +      T.  The conversions allowed by castConvertArguments are a strict
  12.733 +      superset of those performed by convertArguments.
  12.734 +
  12.735 +      In all cases, if S and T are references, a simple checkcast is done.
  12.736 +      If neither S nor T is a primitive, no attempt is made to unbox and
  12.737 +      box.  A failed conversion throws ClassCastException.
  12.738 +
  12.739 +      If T is void, the value is dropped.
  12.740 +
  12.741 +      For compatibility with reflection, if S is void and T is a reference,
  12.742 +      a null value is produced.
  12.743 +
  12.744 +      For compatibility with reflection, if S is a reference and T is a
  12.745 +      primitive, S is first unboxed and then undergoes primitive conversion.
  12.746 +      In the case of 'convertArguments', only assignment conversion is
  12.747 +      performed (no narrowing primitive conversion).
  12.748 +
  12.749 +      If S is a primitive, S is boxed, and then the above rules are applied.
  12.750 +      If S and T are both primitives, the boxing will be undetectable; only
  12.751 +      the primitive conversions will be apparent to the user.  The key point
  12.752 +      is that if S is a primitive type, the implementation may box it and
  12.753 +      treat is as Object, without loss of information, or it may use a "fast
  12.754 +      path" which does not use boxing.
  12.755 +
  12.756 +      Notwithstanding the rules above, for compatibility with the verifier,
  12.757 +      if T is an interface, it is treated as if it were Object.  [KEEP THIS?]
  12.758 +
  12.759 +      Also, for compatibility with the verifier, a boolean may be undergo
  12.760 +      widening or narrowing conversion to any other primitive type.  [KEEP THIS?]
  12.761 +    */
  12.762 +
  12.763 +    /**
  12.764       * Produce a method handle which adapts the calling sequence of the
  12.765       * given method handle to a new type, by reordering the arguments.
  12.766 -     * The resulting method handle is guaranteed to confess a type
  12.767 +     * The resulting method handle is guaranteed to report a type
  12.768       * which is equal to the desired new type.
  12.769       * <p>
  12.770       * The given array controls the reordering.
  12.771 @@ -1092,22 +1175,42 @@
  12.772       * outgoing argument will be taken from the {@code I}-th incoming
  12.773       * argument, where {@code I} is {@code reorder[N]}.
  12.774       * <p>
  12.775 +     * No argument or return value conversions are applied.
  12.776 +     * The type of each incoming argument, as determined by {@code newType},
  12.777 +     * must be identical to the type of the corresponding outgoing argument
  12.778 +     * or arguments in the target method handle.
  12.779 +     * The return type of {@code newType} must be identical to the return
  12.780 +     * type of the original target.
  12.781 +     * <p>
  12.782       * The reordering array need not specify an actual permutation.
  12.783       * An incoming argument will be duplicated if its index appears
  12.784       * more than once in the array, and an incoming argument will be dropped
  12.785       * if its index does not appear in the array.
  12.786 -     * <p>
  12.787 -     * Pairwise conversions are applied as needed to arguments and return
  12.788 -     * values, as with {@link #convertArguments}.
  12.789 +     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
  12.790 +     * incoming arguments which are not mentioned in the reordering array
  12.791 +     * are may be any type, as determined only by {@code newType}.
  12.792 +     * <blockquote><pre>
  12.793 +MethodType intfn1 = MethodType.methodType(int.class, int.class);
  12.794 +MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
  12.795 +MethodHandle sub = ... {int x, int y => x-y} ...;
  12.796 +assert(sub.type().equals(intfn2));
  12.797 +MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
  12.798 +MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
  12.799 +assert((int)rsub.invokeExact(1, 100) == 99);
  12.800 +MethodHandle add = ... {int x, int y => x+y} ...;
  12.801 +assert(add.type().equals(intfn2));
  12.802 +MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
  12.803 +assert(twice.type().equals(intfn1));
  12.804 +assert((int)twice.invokeExact(21) == 42);
  12.805 +     * </pre></blockquote>
  12.806       * @param target the method handle to invoke after arguments are reordered
  12.807       * @param newType the expected type of the new method handle
  12.808       * @param reorder a string which controls the reordering
  12.809 -     * @return a method handle which delegates to {@code target} after performing
  12.810 -     *           any necessary argument motion and conversions, and arranges for any
  12.811 -     *           necessary return value conversions
  12.812 +     * @return a method handle which delegates to {@code target} after it
  12.813 +     *           drops unused arguments and moves and/or duplicates the other arguments
  12.814       */
  12.815      public static
  12.816 -    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
  12.817 +    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
  12.818          MethodType oldType = target.type();
  12.819          checkReorder(reorder, newType, oldType);
  12.820          return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
  12.821 @@ -1130,33 +1233,21 @@
  12.822      }
  12.823  
  12.824      /**
  12.825 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.826 -     * Produce a method handle which adapts the type of the
  12.827 -     * given method handle to a new type, by spreading the final argument.
  12.828 -     * The resulting method handle is guaranteed to confess a type
  12.829 -     * which is equal to the desired new type.
  12.830 -     * <p>
  12.831 -     * The final parameter type of the new type must be an array type T[].
  12.832 -     * This is the type of what is called the <i>spread</i> argument.
  12.833 -     * All other arguments of the new type are called <i>ordinary</i> arguments.
  12.834 -     * <p>
  12.835 -     * The ordinary arguments of the new type are pairwise converted
  12.836 -     * to the initial parameter types of the old type, according to the
  12.837 -     * rules in {@link #convertArguments}.
  12.838 -     * Any additional arguments in the old type
  12.839 -     * are converted from the array element type T,
  12.840 -     * again according to the rules in {@link #convertArguments}.
  12.841 -     * The return value is converted according likewise.
  12.842 -     * <p>
  12.843 -     * The call verifies that the spread argument is in fact an array
  12.844 -     * of exactly the type length, i.e., the excess number of
  12.845 -     * arguments in the old type over the ordinary arguments in the new type.
  12.846 -     * If there are no excess arguments, the spread argument is also
  12.847 -     * allowed to be null.
  12.848 -     * @param target the method handle to invoke after the argument is prepended
  12.849 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
  12.850 +     * Equivalent to the following code:
  12.851 +     * <p><blockquote><pre>
  12.852 +     * int spreadPos = newType.parameterCount() - 1;
  12.853 +     * Class<?> spreadType = newType.parameterType(spreadPos);
  12.854 +     * int spreadCount = target.type().parameterCount() - spreadPos;
  12.855 +     * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
  12.856 +     * adapter = adapter.asType(newType);
  12.857 +     * return adapter;
  12.858 +     * </pre></blockquote>
  12.859 +     * @param target the method handle to invoke after argument spreading
  12.860       * @param newType the expected type of the new method handle
  12.861 -     * @return a new method handle which spreads its final argument,
  12.862 +     * @return a method handle which spreads its final argument,
  12.863       *         before calling the original method handle
  12.864 +     * @deprecated Use {@link MethodHandle#asSpreader}
  12.865       */
  12.866      public static
  12.867      MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
  12.868 @@ -1176,21 +1267,22 @@
  12.869      }
  12.870  
  12.871      /**
  12.872 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.873 -     * Produce a method handle which adapts the type of the
  12.874 -     * given method handle to a new type, by collecting a series of
  12.875 -     * trailing arguments as elements to a single argument array.
  12.876 -     * <p>
  12.877 -     * This method may be used as an inverse to {@link #spreadArguments}.
  12.878 -     * The final parameter type of the old type must be an array type T[],
  12.879 -     * which is the type of what is called the <i>spread</i> argument.
  12.880 -     * The trailing arguments of the new type which correspond to
  12.881 -     * the spread argument are all converted to type T and collected
  12.882 -     * into an array before the original method is called.
  12.883 -     * @param target the method handle to invoke after the argument is prepended
  12.884 +     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
  12.885 +     * Equivalent to the following code:
  12.886 +     * <p><blockquote><pre>
  12.887 +     * int collectPos = target.type().parameterCount() - 1;
  12.888 +     * Class<?> collectType = target.type().parameterType(collectPos);
  12.889 +     * if (!collectType.isArray())  collectType = Object[].class;
  12.890 +     * int collectCount = newType.parameterCount() - collectPos;
  12.891 +     * MethodHandle adapter = target.asCollector(collectType, collectCount);
  12.892 +     * adapter = adapter.asType(newType);
  12.893 +     * return adapter;
  12.894 +     * </pre></blockquote>
  12.895 +     * @param target the method handle to invoke after argument collection
  12.896       * @param newType the expected type of the new method handle
  12.897 -     * @return a new method handle which collects some trailing argument
  12.898 +     * @return a method handle which collects some trailing argument
  12.899       *         into an array, before calling the original method handle
  12.900 +     * @deprecated Use {@link MethodHandle#asCollector} instead.
  12.901       */
  12.902      public static
  12.903      MethodHandle collectArguments(MethodHandle target, MethodType newType) {
  12.904 @@ -1209,7 +1301,88 @@
  12.905      }
  12.906  
  12.907      /**
  12.908 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  12.909 +     * Produce a method handle of the requested return type which returns the given
  12.910 +     * constant value every time it is invoked.
  12.911 +     * <p>
  12.912 +     * Before the method handle is returned, the passed-in value is converted to the requested type.
  12.913 +     * If the requested type is primitive, widening primitive conversions are attempted,
  12.914 +     * else reference conversions are attempted.
  12.915 +     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
  12.916 +     * unless the type is {@code void}, in which case it is {@code identity(type)}.
  12.917 +     * @param type the return type of the desired method handle
  12.918 +     * @param value the value to return
  12.919 +     * @return a method handle of the given return type and no arguments, which always returns the given value
  12.920 +     * @throws WrongMethodTypeException if the value cannot be converted to the required return type
  12.921 +     */
  12.922 +    public static
  12.923 +    MethodHandle constant(Class<?> type, Object value) {
  12.924 +        if (type.isPrimitive()) {
  12.925 +            if (type == void.class)  return identity(type);
  12.926 +            Wrapper w = Wrapper.forPrimitiveType(type);
  12.927 +            return identity(type).bindTo(w.convert(value, type));
  12.928 +        } else {
  12.929 +            return identity(type).bindTo(type.cast(value));
  12.930 +        }
  12.931 +    }
  12.932 +
  12.933 +    /**
  12.934 +     * Produce a method handle of the requested type which returns the given
  12.935 +     * constant value every time it is invoked.
  12.936 +     * <p>
  12.937 +     * Before the method handle is returned, the passed-in value is converted to the requested return type,
  12.938 +     * as if by {@link #explicitCastArguments #explicitCastArguments}.
  12.939 +     * That is, if the return type is primitive, the value is unboxed,
  12.940 +     * and the primitive value is widened and/or narrowed.
  12.941 +     * Otherwise, reference conversions are attempted.
  12.942 +     * @param type the type of the desired method handle
  12.943 +     * @param value the value to return
  12.944 +     * @return a method handle of the given return type and no arguments, which always returns the given value
  12.945 +     * @throws WrongMethodTypeException if the value cannot be converted to the required return type
  12.946 +     */
  12.947 +    public static
  12.948 +    MethodHandle constant(MethodType type, Object value) {
  12.949 +        MethodHandle target = constant(type.returnType(), value);
  12.950 +        int len = type.parameterCount();
  12.951 +        if (len == 0)
  12.952 +            return target.asType(type);
  12.953 +        target = target.asType(type.dropParameterTypes(0, len));
  12.954 +        return dropArguments(target, 0, type.parameterList().subList(0, len));
  12.955 +    }
  12.956 +
  12.957 +     /**
  12.958 +      * Produce a method handle which returns its sole argument when invoked.
  12.959 +      * <p>The identity function for {@code void} takes no arguments and returns no values.
  12.960 +      * @param type the type of the sole parameter and return value of the desired method handle
  12.961 +      * @return a unary method handle which accepts and returns the given type
  12.962 +      */
  12.963 +    public static
  12.964 +    MethodHandle identity(Class<?> type) {
  12.965 +        return ValueConversions.identity(type);
  12.966 +    }
  12.967 +
  12.968 +     /**
  12.969 +      * Produce a method handle of the requested type which returns its argument when invoked.
  12.970 +      * If the return type differs from the first argument type, the argument will be
  12.971 +      * converted as if by {@link #explicitCastArguments explicitCastArguments}.
  12.972 +      * If there are additional arguments beyond the first, they are discarded.
  12.973 +      * <p>The identity function for {@code void} discards all its arguments.
  12.974 +      * @param type the type of the desired method handle
  12.975 +      * @return a method handle of the given type, which always returns its first argument
  12.976 +      * @throws WrongMethodTypeException if the first argument cannot be converted to the required return type
  12.977 +      */
  12.978 +    public static
  12.979 +    MethodHandle identity(MethodType type) {
  12.980 +        MethodHandle target = identity(type.returnType());
  12.981 +        int len = type.parameterCount();
  12.982 +        if (len == 1)
  12.983 +            return explicitCastArguments(target, type);
  12.984 +        if (len == 0)
  12.985 +            throw new IllegalArgumentException("not enough arguments");
  12.986 +        target = explicitCastArguments(target, type.dropParameterTypes(1, len));
  12.987 +        return dropArguments(target, 1, type.parameterList().subList(1, len));
  12.988 +    }
  12.989 +
  12.990 +    /**
  12.991       * Produce a method handle which calls the original method handle {@code target},
  12.992       * after inserting the given argument(s) at the given position.
  12.993       * The formal parameters to {@code target} which will be supplied by those
  12.994 @@ -1229,8 +1402,9 @@
  12.995       * @param target the method handle to invoke after the argument is inserted
  12.996       * @param pos where to insert the argument (zero for the first)
  12.997       * @param values the series of arguments to insert
  12.998 -     * @return a new method handle which inserts an additional argument,
  12.999 +     * @return a method handle which inserts an additional argument,
 12.1000       *         before calling the original method handle
 12.1001 +     * @see MethodHandle#bindTo
 12.1002       */
 12.1003      public static
 12.1004      MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
 12.1005 @@ -1263,14 +1437,7 @@
 12.1006          return result;
 12.1007      }
 12.1008  
 12.1009 -    @Deprecated // "use MethodHandles.insertArguments instead"
 12.1010 -    public static
 12.1011 -    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
 12.1012 -        return insertArguments(target, pos, value);
 12.1013 -    }
 12.1014 -
 12.1015      /**
 12.1016 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1017       * Produce a method handle which calls the original method handle,
 12.1018       * after dropping the given argument(s) at the given position.
 12.1019       * The type of the new method handle will insert the given argument
 12.1020 @@ -1283,25 +1450,25 @@
 12.1021       * <p>
 12.1022       * <b>Example:</b>
 12.1023       * <p><blockquote><pre>
 12.1024 -     *   import static java.dyn.MethodHandles.*;
 12.1025 -     *   import static java.dyn.MethodType.*;
 12.1026 -     *   ...
 12.1027 -     *   MethodHandle cat = lookup().findVirtual(String.class,
 12.1028 -     *     "concat", methodType(String.class, String.class));
 12.1029 -     *   System.out.println((String) cat.invokeExact("x", "y")); // xy
 12.1030 -     *   MethodHandle d0 = dropArguments(cat, 0, String.class);
 12.1031 -     *   System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
 12.1032 -     *   MethodHandle d1 = dropArguments(cat, 1, String.class);
 12.1033 -     *   System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
 12.1034 -     *   MethodHandle d2 = dropArguments(cat, 2, String.class);
 12.1035 -     *   System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
 12.1036 -     *   MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
 12.1037 -     *   System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
 12.1038 +import static java.dyn.MethodHandles.*;
 12.1039 +import static java.dyn.MethodType.*;
 12.1040 +...
 12.1041 +MethodHandle cat = lookup().findVirtual(String.class,
 12.1042 +  "concat", methodType(String.class, String.class));
 12.1043 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
 12.1044 +MethodHandle d0 = dropArguments(cat, 0, String.class);
 12.1045 +assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
 12.1046 +MethodHandle d1 = dropArguments(cat, 1, String.class);
 12.1047 +assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
 12.1048 +MethodHandle d2 = dropArguments(cat, 2, String.class);
 12.1049 +assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
 12.1050 +MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
 12.1051 +assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
 12.1052       * </pre></blockquote>
 12.1053 -     * @param target the method handle to invoke after the argument is dropped
 12.1054 -     * @param valueTypes the type(s) of the argument to drop
 12.1055 -     * @param pos which argument to drop (zero for the first)
 12.1056 -     * @return a new method handle which drops an argument of the given type,
 12.1057 +     * @param target the method handle to invoke after the arguments are dropped
 12.1058 +     * @param valueTypes the type(s) of the argument(s) to drop
 12.1059 +     * @param pos position of first argument to drop (zero for the leftmost)
 12.1060 +     * @return a method handle which drops arguments of the given types,
 12.1061       *         before calling the original method handle
 12.1062       */
 12.1063      public static
 12.1064 @@ -1319,23 +1486,36 @@
 12.1065          return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
 12.1066      }
 12.1067  
 12.1068 +    /**
 12.1069 +     * Produce a method handle which calls the original method handle,
 12.1070 +     * after dropping the given argument(s) at the given position.
 12.1071 +     * The type of the new method handle will insert the given argument
 12.1072 +     * type(s), at that position, into the original handle's type.
 12.1073 +     * This method is equivalent to the following code:
 12.1074 +     * <code>
 12.1075 +     * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
 12.1076 +     * </code>
 12.1077 +     * @param target the method handle to invoke after the arguments are dropped
 12.1078 +     * @param valueTypes the type(s) of the argument(s) to drop
 12.1079 +     * @param pos position of first argument to drop (zero for the leftmost)
 12.1080 +     * @return a method handle which drops arguments of the given types,
 12.1081 +     *         before calling the original method handle
 12.1082 +     */
 12.1083      public static
 12.1084      MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
 12.1085          return dropArguments(target, pos, Arrays.asList(valueTypes));
 12.1086      }
 12.1087  
 12.1088      /**
 12.1089 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1090       * Adapt a target method handle {@code target} by pre-processing
 12.1091       * one or more of its arguments, each with its own unary filter function,
 12.1092       * and then calling the target with each pre-processed argument
 12.1093       * replaced by the result of its corresponding filter function.
 12.1094       * <p>
 12.1095       * The pre-processing is performed by one or more method handles,
 12.1096 -     * specified in the non-null elements of the {@code filters} array.
 12.1097 -     * (If there are no such elements, the original target is returned.)
 12.1098 -     * Each filter (that is, each non-null element of {@code filters})
 12.1099 -     * is applied to the corresponding argument of the adapter.
 12.1100 +     * specified in the elements of the {@code filters} array.
 12.1101 +     * (If there are no elements in the array, the original target is returned.)
 12.1102 +     * Each filter is applied to the corresponding argument of the adapter.
 12.1103       * <p>
 12.1104       * If a filter {@code F} applies to the {@code N}th argument of
 12.1105       * the method handle, then {@code F} must be a method handle which
 12.1106 @@ -1345,46 +1525,49 @@
 12.1107       * The return type of {@code F} must be identical to the corresponding
 12.1108       * parameter type of the target.
 12.1109       * <p>
 12.1110 -     * It is an error if there are non-null elements of {@code filters}
 12.1111 +     * It is an error if there are elements of {@code filters}
 12.1112       * which do not correspond to argument positions in the target.
 12.1113 -     * The actual length of the target array may be any number, it need
 12.1114 -     * not be the same as the parameter count of the target type.
 12.1115 -     * (This provides an easy way to filter just the first argument or two
 12.1116 -     * of a target method handle.)
 12.1117 -     * <p> Here is pseudocode for the resulting adapter:
 12.1118 -     * <blockquote><pre>
 12.1119 -     * // there are N arguments in the A sequence
 12.1120 -     * T target(A[N]...);
 12.1121 -     * [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
 12.1122 -     * T adapter(B[N]... b) {
 12.1123 -     *   A[N] a...;
 12.1124 -     *   [i&lt;N] a[i] = filter[i](b[i]);
 12.1125 -     *   return target(a...);
 12.1126 -     * }
 12.1127 +     * <b>Example:</b>
 12.1128 +     * <p><blockquote><pre>
 12.1129 +import static java.dyn.MethodHandles.*;
 12.1130 +import static java.dyn.MethodType.*;
 12.1131 +...
 12.1132 +MethodHandle cat = lookup().findVirtual(String.class,
 12.1133 +  "concat", methodType(String.class, String.class));
 12.1134 +MethodHandle upcase = lookup().findVirtual(String.class,
 12.1135 +  "toUpperCase", methodType(String.class));
 12.1136 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
 12.1137 +MethodHandle f0 = filterArguments(cat, 0, upcase);
 12.1138 +assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
 12.1139 +MethodHandle f1 = filterArguments(cat, 1, upcase);
 12.1140 +assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
 12.1141 +MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
 12.1142 +assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
 12.1143       * </pre></blockquote>
 12.1144       * @param target the method handle to invoke after arguments are filtered
 12.1145 +     * @param pos the position of the first argument to filter
 12.1146       * @param filters method handles to call initially on filtered arguments
 12.1147       * @return method handle which incorporates the specified argument filtering logic
 12.1148 -     * @throws IllegalArgumentException if a non-null element of {@code filters}
 12.1149 -     *          does not match a corresponding argument type of {@code target}
 12.1150 +     * @throws IllegalArgumentException if an element of {@code filters} is null or
 12.1151 +     *          does not match a corresponding argument type of {@code target} as described above
 12.1152       */
 12.1153      public static
 12.1154 -    MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
 12.1155 +    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
 12.1156          MethodType targetType = target.type();
 12.1157          MethodHandle adapter = target;
 12.1158          MethodType adapterType = targetType;
 12.1159 -        int pos = -1, maxPos = targetType.parameterCount();
 12.1160 +        int maxPos = targetType.parameterCount();
 12.1161 +        int curPos = pos;
 12.1162          for (MethodHandle filter : filters) {
 12.1163 -            pos += 1;
 12.1164 -            if (filter == null)  continue;
 12.1165 -            if (pos >= maxPos)
 12.1166 +            if (curPos >= maxPos)
 12.1167                  throw newIllegalArgumentException("too many filters");
 12.1168              MethodType filterType = filter.type();
 12.1169              if (filterType.parameterCount() != 1
 12.1170 -                || filterType.returnType() != targetType.parameterType(pos))
 12.1171 +                || filterType.returnType() != targetType.parameterType(curPos))
 12.1172                  throw newIllegalArgumentException("target and filter types do not match");
 12.1173 -            adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
 12.1174 -            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
 12.1175 +            adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
 12.1176 +            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter);
 12.1177 +            curPos += 1;
 12.1178          }
 12.1179          MethodType midType = adapter.type();
 12.1180          if (midType != adapterType)
 12.1181 @@ -1393,7 +1576,48 @@
 12.1182      }
 12.1183  
 12.1184      /**
 12.1185 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1186 +     * Adapt a target method handle {@code target} by post-processing
 12.1187 +     * its return value with a unary filter function.
 12.1188 +     * <p>
 12.1189 +     * If a filter {@code F} applies to the return value of
 12.1190 +     * the target method handle, then {@code F} must be a method handle which
 12.1191 +     * takes exactly one argument.  The return type of {@code F}
 12.1192 +     * replaces the return type of the target
 12.1193 +     * in the resulting adapted method handle.
 12.1194 +     * The argument type of {@code F} must be identical to the
 12.1195 +     * return type of the target.
 12.1196 +     * <b>Example:</b>
 12.1197 +     * <p><blockquote><pre>
 12.1198 +import static java.dyn.MethodHandles.*;
 12.1199 +import static java.dyn.MethodType.*;
 12.1200 +...
 12.1201 +MethodHandle cat = lookup().findVirtual(String.class,
 12.1202 +  "concat", methodType(String.class, String.class));
 12.1203 +MethodHandle length = lookup().findVirtual(String.class,
 12.1204 +  "length", methodType(int.class));
 12.1205 +System.out.println((String) cat.invokeExact("x", "y")); // xy
 12.1206 +MethodHandle f0 = filterReturnValue(cat, length);
 12.1207 +System.out.println((int) f0.invokeExact("x", "y")); // 2
 12.1208 +     * </pre></blockquote>
 12.1209 +     * @param target the method handle to invoke before filtering the return value
 12.1210 +     * @param filter method handle to call on the return value
 12.1211 +     * @return method handle which incorporates the specified return value filtering logic
 12.1212 +     * @throws IllegalArgumentException if {@code filter} is null or
 12.1213 +     *          does not match the return type of {@code target} as described above
 12.1214 +     */
 12.1215 +    public static
 12.1216 +    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
 12.1217 +        MethodType targetType = target.type();
 12.1218 +        MethodType filterType = filter.type();
 12.1219 +        if (filterType.parameterCount() != 1
 12.1220 +            || filterType.parameterType(0) != targetType.returnType())
 12.1221 +            throw newIllegalArgumentException("target and filter types do not match");
 12.1222 +        // FIXME: Too many nodes here.
 12.1223 +        MethodHandle returner = dropArguments(filter, 0, targetType.parameterList());
 12.1224 +        return foldArguments(returner, exactInvoker(target.type()).bindTo(target));
 12.1225 +    }
 12.1226 +
 12.1227 +    /**
 12.1228       * Adapt a target method handle {@code target} by pre-processing
 12.1229       * some of its arguments, and then calling the target with
 12.1230       * the result of the pre-processing, plus all original arguments.
 12.1231 @@ -1410,10 +1634,10 @@
 12.1232       * The resulting adapter is the same type as the target, except that the
 12.1233       * initial argument type of the target is dropped.
 12.1234       * <p>
 12.1235 -     * (Note that {@link #dropArguments} can be used to remove any arguments
 12.1236 +     * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
 12.1237       * that either the {@code combiner} or {@code target} does not wish to receive.
 12.1238       * If some of the incoming arguments are destined only for the combiner,
 12.1239 -     * consider using {@link #collectArguments} instead, since those
 12.1240 +     * consider using {@link MethodHandle#asCollector} instead, since those
 12.1241       * arguments will not need to be live on the stack on entry to the
 12.1242       * target.)
 12.1243       * <p>
 12.1244 @@ -1434,7 +1658,7 @@
 12.1245       * @return method handle which incorporates the specified argument folding logic
 12.1246       * @throws IllegalArgumentException if the first argument type of
 12.1247       *          {@code target} is not the same as {@code combiner}'s return type,
 12.1248 -     *          or if the next {@code foldArgs} argument types of {@code target}
 12.1249 +     *          or if the following argument types of {@code target}
 12.1250       *          are not identical with the argument types of {@code combiner}
 12.1251       */
 12.1252      public static
 12.1253 @@ -1443,6 +1667,10 @@
 12.1254          MethodType combinerType = combiner.type();
 12.1255          int foldArgs = combinerType.parameterCount();
 12.1256          boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
 12.1257 +        if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
 12.1258 +            ok = false;
 12.1259 +        if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
 12.1260 +            ok = false;
 12.1261          if (!ok)
 12.1262              throw misMatchedTypes("target and combiner types", targetType, combinerType);
 12.1263          MethodType newType = targetType.dropParameterTypes(0, 1);
 12.1264 @@ -1450,7 +1678,6 @@
 12.1265      }
 12.1266  
 12.1267      /**
 12.1268 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1269       * Make a method handle which adapts a target method handle,
 12.1270       * by guarding it with a test, a boolean-valued method handle.
 12.1271       * If the guard fails, a fallback handle is called instead.
 12.1272 @@ -1470,6 +1697,9 @@
 12.1273       *     return fallback(a..., b...);
 12.1274       * }
 12.1275       * </pre></blockquote>
 12.1276 +     * Note that the test arguments ({@code a...} in the pseudocode) cannot
 12.1277 +     * be modified by execution of the test, and so are passed unchanged
 12.1278 +     * from the caller to the target or fallback as appropriate.
 12.1279       * @param test method handle used for test, must return boolean
 12.1280       * @param target method handle to call if test passes
 12.1281       * @param fallback method handle to call if test fails
 12.1282 @@ -1485,40 +1715,19 @@
 12.1283          MethodType gtype = test.type();
 12.1284          MethodType ttype = target.type();
 12.1285          MethodType ftype = fallback.type();
 12.1286 -        if (ttype != ftype)
 12.1287 +        if (!ttype.equals(ftype))
 12.1288              throw misMatchedTypes("target and fallback types", ttype, ftype);
 12.1289 -        MethodType gtype2 = ttype.changeReturnType(boolean.class);
 12.1290 -        if (gtype2 != gtype) {
 12.1291 -            if (gtype.returnType() != boolean.class)
 12.1292 -                throw newIllegalArgumentException("guard type is not a predicate "+gtype);
 12.1293 -            int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
 12.1294 -            if (gpc < tpc) {
 12.1295 -                test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
 12.1296 -                gtype = test.type();
 12.1297 -            }
 12.1298 -            if (gtype2 != gtype)
 12.1299 +        if (gtype.returnType() != boolean.class)
 12.1300 +            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
 12.1301 +        List<Class<?>> targs = ttype.parameterList();
 12.1302 +        List<Class<?>> gargs = gtype.parameterList();
 12.1303 +        if (!targs.equals(gargs)) {
 12.1304 +            int gpc = gargs.size(), tpc = targs.size();
 12.1305 +            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
 12.1306                  throw misMatchedTypes("target and test types", ttype, gtype);
 12.1307 +            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
 12.1308 +            gtype = test.type();
 12.1309          }
 12.1310 -        /* {
 12.1311 -            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
 12.1312 -            static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
 12.1313 -                return z ? t : f;
 12.1314 -            }
 12.1315 -            static MethodHandle compose(MethodHandle f, MethodHandle g) {
 12.1316 -                Class<?> initargs = g.type().parameterArray();
 12.1317 -                f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
 12.1318 -                return combineArguments(f, g);
 12.1319 -            }
 12.1320 -            // choose = \z.(z ? target : fallback)
 12.1321 -            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
 12.1322 -                    MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
 12.1323 -            choose = appendArgument(choose, target);
 12.1324 -            choose = appendArgument(choose, fallback);
 12.1325 -            MethodHandle dispatch = compose(choose, test);
 12.1326 -            // dispatch = \(a...).(test(a...) ? target : fallback)
 12.1327 -            return combineArguments(invoke, dispatch, 0);
 12.1328 -            // return \(a...).((test(a...) ? target : fallback).invokeExact(a...))
 12.1329 -        } */
 12.1330          return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
 12.1331      }
 12.1332  
 12.1333 @@ -1527,29 +1736,38 @@
 12.1334      }
 12.1335  
 12.1336      /**
 12.1337 -     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1338       * Make a method handle which adapts a target method handle,
 12.1339       * by running it inside an exception handler.
 12.1340       * If the target returns normally, the adapter returns that value.
 12.1341       * If an exception matching the specified type is thrown, the fallback
 12.1342       * handle is called instead on the exception, plus the original arguments.
 12.1343       * <p>
 12.1344 -     * The handler must have leading parameter of {@code exType} or a supertype,
 12.1345 -     * followed by arguments which correspond <em>(how? TBD)</em> to
 12.1346 -     * all the parameters of the target.
 12.1347 -     * The target and handler must return the same type.
 12.1348 +     * The target and handler must have the same corresponding
 12.1349 +     * argument and return types, except that handler may omit trailing arguments
 12.1350 +     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
 12.1351 +     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
 12.1352       * <p> Here is pseudocode for the resulting adapter:
 12.1353       * <blockquote><pre>
 12.1354 -     * T target(A...);
 12.1355 +     * T target(A..., B...);
 12.1356       * T handler(ExType, A...);
 12.1357 -     * T adapter(A... a) {
 12.1358 +     * T adapter(A... a, B... b) {
 12.1359       *   try {
 12.1360 -     *     return target(a...);
 12.1361 +     *     return target(a..., b...);
 12.1362       *   } catch (ExType ex) {
 12.1363       *     return handler(ex, a...);
 12.1364       *   }
 12.1365       * }
 12.1366       * </pre></blockquote>
 12.1367 +     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
 12.1368 +     * be modified by execution of the target, and so are passed unchanged
 12.1369 +     * from the caller to the handler, if the handler is invoked.
 12.1370 +     * <p>
 12.1371 +     * The target and handler must return the same type, even if the handler
 12.1372 +     * always throws.  (This might happen, for instance, because the handler
 12.1373 +     * is simulating a {@code finally} clause).
 12.1374 +     * To create such a throwing handler, compose the handler creation logic
 12.1375 +     * with {@link #throwException throwException},
 12.1376 +     * in order to create a method handle of the correct return type.
 12.1377       * @param target method handle to call
 12.1378       * @param exType the type of exception which the handler will catch
 12.1379       * @param handler method handle to call if a matching exception is thrown
 12.1380 @@ -1563,16 +1781,23 @@
 12.1381      MethodHandle catchException(MethodHandle target,
 12.1382                                  Class<? extends Throwable> exType,
 12.1383                                  MethodHandle handler) {
 12.1384 -        MethodType targetType = target.type();
 12.1385 -        MethodType handlerType = handler.type();
 12.1386 -        boolean ok = (targetType.parameterCount() ==
 12.1387 -                      handlerType.parameterCount() - 1);
 12.1388 -//        for (int i = 0; ok && i < numExArgs; i++) {
 12.1389 -//            if (targetType.parameterType(i) != handlerType.parameterType(1+i))
 12.1390 -//                ok = false;
 12.1391 -//        }
 12.1392 -        if (!ok)
 12.1393 -            throw newIllegalArgumentException("target and handler types do not match");
 12.1394 +        MethodType ttype = target.type();
 12.1395 +        MethodType htype = handler.type();
 12.1396 +        if (htype.parameterCount() < 1 ||
 12.1397 +            !htype.parameterType(0).isAssignableFrom(exType))
 12.1398 +            throw newIllegalArgumentException("handler does not accept exception type "+exType);
 12.1399 +        if (htype.returnType() != ttype.returnType())
 12.1400 +            throw misMatchedTypes("target and handler return types", ttype, htype);
 12.1401 +        List<Class<?>> targs = ttype.parameterList();
 12.1402 +        List<Class<?>> hargs = htype.parameterList();
 12.1403 +        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
 12.1404 +        if (!targs.equals(hargs)) {
 12.1405 +            int hpc = hargs.size(), tpc = targs.size();
 12.1406 +            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
 12.1407 +                throw misMatchedTypes("target and handler types", ttype, htype);
 12.1408 +            handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
 12.1409 +            htype = handler.type();
 12.1410 +        }
 12.1411          return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
 12.1412      }
 12.1413  
 12.1414 @@ -1590,10 +1815,11 @@
 12.1415      }
 12.1416  
 12.1417      /**
 12.1418 -     * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
 12.1419 -     * A SAM type is a type which declares a single abstract method.
 12.1420 -     * Additionally, it must have either no constructor (as an interface)
 12.1421 -     * or have a public or protected constructor of zero arguments (as a class).
 12.1422 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1423 +     * Produce a wrapper instance of the given "SAM" interface which redirects
 12.1424 +     * its calls to the given method handle.
 12.1425 +     * A SAM interface is an interface which declares a single abstract method.
 12.1426 +     * The type must be public.  (No additional access checks are performed.)
 12.1427       * <p>
 12.1428       * The resulting instance of the required SAM type will respond to
 12.1429       * invocation of the SAM type's single abstract method by calling
 12.1430 @@ -1605,9 +1831,9 @@
 12.1431       * The method handle may throw an <em>undeclared exception</em>,
 12.1432       * which means any checked exception (or other checked throwable)
 12.1433       * not declared by the SAM type's single abstract method.
 12.1434 -     * If this happens, the throwable will be wrapped in an instance
 12.1435 -     * of {@link UndeclaredThrowableException} and thrown in that
 12.1436 -     * wrapped form.
 12.1437 +     * If this happens, the throwable will be wrapped in an instance of
 12.1438 +     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
 12.1439 +     * and thrown in that wrapped form.
 12.1440       * <p>
 12.1441       * The wrapper instance is guaranteed to be of a non-public
 12.1442       * implementation class C in a package containing no classes
 12.1443 @@ -1618,19 +1844,36 @@
 12.1444       * <li>the SAM type itself and any methods in the SAM type
 12.1445       * <li>the supertypes of the SAM type (if any) and their methods
 12.1446       * <li>{@link Object} and its methods
 12.1447 -     * <li>{@link MethodHandleProvider} and its methods
 12.1448 +     * <li>{@link java.dyn.AsInstanceObject AsInstanceObject} and its methods</li>
 12.1449       * </ul>
 12.1450       * <p>
 12.1451 +     * (Note: When determining the unique abstract method of a SAM interface,
 12.1452 +     * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
 12.1453 +     * are disregarded.  For example, {@link java.util.Comparator} is a SAM interface,
 12.1454 +     * even though it re-declares the {@code Object.equals} method.)
 12.1455 +     * <p>
 12.1456       * No stable mapping is promised between the SAM type and
 12.1457       * the implementation class C.  Over time, several implementation
 12.1458       * classes might be used for the same SAM type.
 12.1459       * <p>
 12.1460       * This method is not guaranteed to return a distinct
 12.1461 -     * wrapper object for each separate call.  If the JVM is able
 12.1462 -     * to prove that a wrapper has already been created for a given
 12.1463 +     * wrapper object for each separate call.  If the implementation is able
 12.1464 +     * to prove that a wrapper of the required SAM type
 12.1465 +     * has already been created for a given
 12.1466       * method handle, or for another method handle with the
 12.1467 -     * same behavior, the JVM may return that wrapper in place of
 12.1468 +     * same behavior, the implementation may return that wrapper in place of
 12.1469       * a new wrapper.
 12.1470 +     * <p>
 12.1471 +     * This method is designed to apply to common use cases
 12.1472 +     * where a single method handle must interoperate with
 12.1473 +     * a type (class or interface) that implements a function-like
 12.1474 +     * API.  Additional variations, such as SAM classes with
 12.1475 +     * private constructors, or interfaces with multiple but related
 12.1476 +     * entry points, must be covered by hand-written or automatically
 12.1477 +     * generated adapter classes.  In those cases, consider implementing
 12.1478 +     * {@link java.dyn.MethodHandles.AsInstanceObject AsInstanceObject}
 12.1479 +     * in the adapters, so that generic code can extract the underlying
 12.1480 +     * method handle without knowing where the SAM adapter came from.
 12.1481       * @param target the method handle to invoke from the wrapper
 12.1482       * @param samType the desired type of the wrapper, a SAM type
 12.1483       * @return a correctly-typed wrapper for the given {@code target}
 12.1484 @@ -1639,38 +1882,93 @@
 12.1485       */
 12.1486      // ISSUE: Should we delegate equals/hashCode to the targets?
 12.1487      // Not useful unless there is a stable equals/hashCode behavior
 12.1488 -    // for MethodHandle, and for MethodHandleProvider.asMethodHandle.
 12.1489 +    // for MethodHandle, but there isn't.
 12.1490      public static
 12.1491 -    <T> T asInstance(MethodHandle target, Class<T> samType) {
 12.1492 +    <T> T asInstance(final MethodHandle target, final Class<T> samType) {
 12.1493          // POC implementation only; violates the above contract several ways
 12.1494          final Method sam = getSamMethod(samType);
 12.1495          if (sam == null)
 12.1496              throw new IllegalArgumentException("not a SAM type: "+samType.getName());
 12.1497          MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
 12.1498          if (!samMT.equals(target.type()))
 12.1499 -            throw new IllegalArgumentException("wrong method type");
 12.1500 -        final MethodHandle mh = target;
 12.1501 +            throw new IllegalArgumentException("wrong method type: "+target+" should match "+sam);
 12.1502          return samType.cast(Proxy.newProxyInstance(
 12.1503                  samType.getClassLoader(),
 12.1504 -                new Class[]{ samType, MethodHandleProvider.class },
 12.1505 +                new Class[]{ samType, AsInstanceObject.class },
 12.1506                  new InvocationHandler() {
 12.1507 +                    private Object getArg(String name) {
 12.1508 +                        if ((Object)name == "getAsInstanceTarget")  return target;
 12.1509 +                        if ((Object)name == "getAsInstanceType")    return samType;
 12.1510 +                        throw new AssertionError();
 12.1511 +                    }
 12.1512                      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 12.1513 -                        if (method.getDeclaringClass() == MethodHandleProvider.class) {
 12.1514 -                            return method.invoke(mh, args);
 12.1515 -                        }
 12.1516 -                        assert method.equals(sam) : method;
 12.1517 -                        return mh.invokeVarargs(args);
 12.1518 +                        if (method.getDeclaringClass() == AsInstanceObject.class)
 12.1519 +                            return getArg(method.getName());
 12.1520 +                        if (method.equals(sam))
 12.1521 +                            return target.invokeVarargs(args);
 12.1522 +                        if (isObjectMethod(method))
 12.1523 +                            return callObjectMethod(this, method, args);
 12.1524 +                        throw new InternalError();
 12.1525                      }
 12.1526                  }));
 12.1527      }
 12.1528  
 12.1529 +    /**
 12.1530 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 12.1531 +     * Interface implemented by every object which is produced by {@link #asInstance asInstance}.
 12.1532 +     * The methods of this interface allow a caller to recover the parameters
 12.1533 +     * to {@code asInstance}.
 12.1534 +     * This allows applications to repeatedly convert between method handles
 12.1535 +     * and SAM objects, without the risk of creating unbounded delegation chains.
 12.1536 +     */
 12.1537 +    public interface AsInstanceObject {
 12.1538 +        /** Produce or recover a target method handle which is behaviorally
 12.1539 +         *  equivalent to the SAM method of this object.
 12.1540 +         */
 12.1541 +        public MethodHandle getAsInstanceTarget();
 12.1542 +        /** Recover the SAM type for which this object was created.
 12.1543 +         */
 12.1544 +        public Class<?> getAsInstanceType();
 12.1545 +    }
 12.1546 +
 12.1547 +    private static
 12.1548 +    boolean isObjectMethod(Method m) {
 12.1549 +        switch (m.getName()) {
 12.1550 +        case "toString":
 12.1551 +            return (m.getReturnType() == String.class
 12.1552 +                    && m.getParameterTypes().length == 0);
 12.1553 +        case "hashCode":
 12.1554 +            return (m.getReturnType() == int.class
 12.1555 +                    && m.getParameterTypes().length == 0);
 12.1556 +        case "equals":
 12.1557 +            return (m.getReturnType() == boolean.class
 12.1558 +                    && m.getParameterTypes().length == 1
 12.1559 +                    && m.getParameterTypes()[0] == Object.class);
 12.1560 +        }
 12.1561 +        return false;
 12.1562 +    }
 12.1563 +
 12.1564 +    private static
 12.1565 +    Object callObjectMethod(Object self, Method m, Object[] args) {
 12.1566 +        assert(isObjectMethod(m)) : m;
 12.1567 +        switch (m.getName()) {
 12.1568 +        case "toString":
 12.1569 +            return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
 12.1570 +        case "hashCode":
 12.1571 +            return System.identityHashCode(self);
 12.1572 +        case "equals":
 12.1573 +            return (self == args[0]);
 12.1574 +        }
 12.1575 +        return null;
 12.1576 +    }
 12.1577 +
 12.1578      private static
 12.1579      Method getSamMethod(Class<?> samType) {
 12.1580          Method sam = null;
 12.1581          for (Method m : samType.getMethods()) {
 12.1582              int mod = m.getModifiers();
 12.1583              if (Modifier.isAbstract(mod)) {
 12.1584 -                if (sam != null)
 12.1585 +                if (sam != null && !isObjectMethod(sam))
 12.1586                      return null;  // too many abstract methods
 12.1587                  sam = m;
 12.1588              }
 12.1589 @@ -1691,4 +1989,9 @@
 12.1590          }
 12.1591          return null;
 12.1592      }
 12.1593 +
 12.1594 +    /*non-public*/
 12.1595 +    static MethodHandle withTypeHandler(MethodHandle target, MethodHandle typeHandler) {
 12.1596 +        return MethodHandleImpl.withTypeHandler(IMPL_TOKEN, target, typeHandler);
 12.1597 +    }
 12.1598  }
    13.1 --- a/src/share/classes/java/dyn/MethodType.java	Tue Dec 21 15:27:55 2010 -0800
    13.2 +++ b/src/share/classes/java/dyn/MethodType.java	Tue Dec 21 18:45:45 2010 -0800
    13.3 @@ -56,21 +56,33 @@
    13.4   * <p>
    13.5   * This type can be created only by factory methods.
    13.6   * All factory methods may cache values, though caching is not guaranteed.
    13.7 + * Some factory methods are static, while others are virtual methods which
    13.8 + * modify precursor method types, e.g., by changing a selected parameter.
    13.9 + * <p>
   13.10 + * Factory methods which operate on groups of parameter types
   13.11 + * are systematically presented in two versions, so that both Java arrays and
   13.12 + * Java lists can be used to work with groups of parameter types.
   13.13 + * The query methods {@code parameterArray} and {@code parameterList}
   13.14 + * also provide a choice between arrays and lists.
   13.15   * <p>
   13.16   * {@code MethodType} objects are sometimes derived from bytecode instructions
   13.17   * such as {@code invokedynamic}, specifically from the type descriptor strings associated
   13.18   * with the instructions in a class file's constant pool.
   13.19 - * When this occurs, any classes named in the descriptor strings must be loaded.
   13.20 - * (But they need not be initialized.)
   13.21 + * <p>
   13.22 + * Like classes and strings, method types can also be represented directly
   13.23 + * in a class file's constant pool as constants. The may be loaded by an {@code ldc}
   13.24 + * instruction which refers to a suitable {@code CONSTANT_MethodType} constant pool entry.
   13.25 + * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
   13.26 + * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
   13.27 + * <p>
   13.28 + * When the JVM materializes a {@code MethodType} from a descriptor string,
   13.29 + * all classes named in the descriptor must be accessible, and will be loaded.
   13.30 + * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
   13.31   * This loading may occur at any time before the {@code MethodType} object is first derived.
   13.32 - * <p>
   13.33 - * Like classes and strings, method types can be represented directly
   13.34 - * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
   13.35 - * Loading such a constant causes its component classes to be loaded as necessary.
   13.36   * @author John Rose, JSR 292 EG
   13.37   */
   13.38  public final
   13.39 -class MethodType implements java.lang.reflect.Type {
   13.40 +class MethodType {
   13.41      private final Class<?>   rtype;
   13.42      private final Class<?>[] ptypes;
   13.43      private MethodTypeForm form; // erased form, plus cached data about primitives
   13.44 @@ -119,7 +131,7 @@
   13.45          for (Class<?> ptype : ptypes) {
   13.46              ptype.equals(ptype);  // null check
   13.47              if (ptype == void.class)
   13.48 -                throw newIllegalArgumentException("void parameter: "+this);
   13.49 +                throw newIllegalArgumentException("parameter type cannot be void");
   13.50          }
   13.51      }
   13.52  
   13.53 @@ -139,10 +151,6 @@
   13.54      MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
   13.55          return makeImpl(rtype, ptypes, false);
   13.56      }
   13.57 -    @Deprecated public static
   13.58 -    MethodType make(Class<?> rtype, Class<?>[] ptypes) {
   13.59 -        return methodType(rtype, ptypes);
   13.60 -    }
   13.61  
   13.62      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
   13.63      public static
   13.64 @@ -150,10 +158,6 @@
   13.65          boolean notrust = false;  // random List impl. could return evil ptypes array
   13.66          return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
   13.67      }
   13.68 -    @Deprecated public static
   13.69 -    MethodType make(Class<?> rtype, List<? extends Class<?>> ptypes) {
   13.70 -        return methodType(rtype, ptypes);
   13.71 -    }
   13.72  
   13.73      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
   13.74       *  The leading parameter type is prepended to the remaining array.
   13.75 @@ -165,10 +169,6 @@
   13.76          System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
   13.77          return makeImpl(rtype, ptypes1, true);
   13.78      }
   13.79 -    @Deprecated public static
   13.80 -    MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
   13.81 -        return methodType(rtype, ptype0, ptypes);
   13.82 -    }
   13.83  
   13.84      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
   13.85       *  The resulting method has no parameter types.
   13.86 @@ -177,10 +177,6 @@
   13.87      MethodType methodType(Class<?> rtype) {
   13.88          return makeImpl(rtype, NO_PTYPES, true);
   13.89      }
   13.90 -    @Deprecated public static
   13.91 -    MethodType make(Class<?> rtype) {
   13.92 -        return methodType(rtype);
   13.93 -    }
   13.94  
   13.95      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
   13.96       *  The resulting method has the single given parameter type.
   13.97 @@ -189,10 +185,6 @@
   13.98      MethodType methodType(Class<?> rtype, Class<?> ptype0) {
   13.99          return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
  13.100      }
  13.101 -    @Deprecated public static
  13.102 -    MethodType make(Class<?> rtype, Class<?> ptype0) {
  13.103 -        return methodType(rtype, ptype0);
  13.104 -    }
  13.105  
  13.106      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.107       *  The resulting method has the same parameter types as {@code ptypes},
  13.108 @@ -202,10 +194,6 @@
  13.109      MethodType methodType(Class<?> rtype, MethodType ptypes) {
  13.110          return makeImpl(rtype, ptypes.ptypes, true);
  13.111      }
  13.112 -    @Deprecated public static
  13.113 -    MethodType make(Class<?> rtype, MethodType ptypes) {
  13.114 -        return methodType(rtype, ptypes);
  13.115 -    }
  13.116  
  13.117      /**
  13.118       * Sole factory method to find or create an interned method type.
  13.119 @@ -275,10 +263,6 @@
  13.120          }
  13.121          return mt;
  13.122      }
  13.123 -    @Deprecated public static
  13.124 -    MethodType makeGeneric(int objectArgCount, boolean varargs) {
  13.125 -        return genericMethodType(objectArgCount, varargs);
  13.126 -    }
  13.127  
  13.128      /**
  13.129       * All parameters and the return type will be Object.
  13.130 @@ -290,10 +274,6 @@
  13.131      MethodType genericMethodType(int objectArgCount) {
  13.132          return genericMethodType(objectArgCount, false);
  13.133      }
  13.134 -    @Deprecated public static
  13.135 -    MethodType makeGeneric(int objectArgCount) {
  13.136 -        return genericMethodType(objectArgCount);
  13.137 -    }
  13.138  
  13.139      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.140       * @param num    the index (zero-based) of the parameter type to change
  13.141 @@ -307,18 +287,6 @@
  13.142          return makeImpl(rtype, nptypes, true);
  13.143      }
  13.144  
  13.145 -    /** Convenience method for {@link #insertParameterTypes}.
  13.146 -     * @deprecated Use {@link #insertParameterTypes} instead.
  13.147 -     */
  13.148 -    @Deprecated
  13.149 -    public MethodType insertParameterType(int num, Class<?> nptype) {
  13.150 -        int len = ptypes.length;
  13.151 -        Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1);
  13.152 -        System.arraycopy(nptypes, num, nptypes, num+1, len-num);
  13.153 -        nptypes[num] = nptype;
  13.154 -        return makeImpl(rtype, nptypes, true);
  13.155 -    }
  13.156 -
  13.157      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.158       * @param num    the position (zero-based) of the inserted parameter type(s)
  13.159       * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
  13.160 @@ -337,6 +305,22 @@
  13.161      }
  13.162  
  13.163      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.164 +     * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
  13.165 +     * @return the same type, except with the selected parameter(s) appended
  13.166 +     */
  13.167 +    public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
  13.168 +        return insertParameterTypes(parameterCount(), ptypesToInsert);
  13.169 +    }
  13.170 +
  13.171 +    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.172 +     * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
  13.173 +     * @return the same type, except with the selected parameter(s) appended
  13.174 +     */
  13.175 +    public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
  13.176 +        return insertParameterTypes(parameterCount(), ptypesToInsert);
  13.177 +    }
  13.178 +
  13.179 +    /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.180       * @param num    the position (zero-based) of the inserted parameter type(s)
  13.181       * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
  13.182       * @return the same type, except with the selected parameter(s) inserted
  13.183 @@ -377,14 +361,6 @@
  13.184          return makeImpl(rtype, nptypes, true);
  13.185      }
  13.186  
  13.187 -    /** Convenience method for {@link #dropParameterTypes}.
  13.188 -     * @deprecated Use {@link #dropParameterTypes} instead.
  13.189 -     */
  13.190 -    @Deprecated
  13.191 -    public MethodType dropParameterType(int num) {
  13.192 -        return dropParameterTypes(num, num+1);
  13.193 -    }
  13.194 -
  13.195      /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
  13.196       * @param nrtype a return parameter type to replace the old one with
  13.197       * @return the same type, except with the return type change
  13.198 @@ -552,7 +528,9 @@
  13.199       * parenthesis enclosed, comma separated list of type names,
  13.200       * followed immediately by the return type.
  13.201       * <p>
  13.202 -     * If a type name is array, it the base type followed
  13.203 +     * Each type is represented by its
  13.204 +     * {@link java.lang.Class#getSimpleName simple name}.
  13.205 +     * If a type name name is array, it the base type followed
  13.206       * by [], rather than the Class.getName of the array type.
  13.207       */
  13.208      @Override
  13.209 @@ -561,35 +539,13 @@
  13.210          sb.append("(");
  13.211          for (int i = 0; i < ptypes.length; i++) {
  13.212              if (i > 0)  sb.append(",");
  13.213 -            putName(sb, ptypes[i]);
  13.214 +            sb.append(ptypes[i].getSimpleName());
  13.215          }
  13.216          sb.append(")");
  13.217 -        putName(sb, rtype);
  13.218 +        sb.append(rtype.getSimpleName());
  13.219          return sb.toString();
  13.220      }
  13.221  
  13.222 -    static void putName(StringBuilder sb, Class<?> cls) {
  13.223 -        int brackets = 0;
  13.224 -        while (cls.isArray()) {
  13.225 -            cls = cls.getComponentType();
  13.226 -            brackets++;
  13.227 -        }
  13.228 -        String n = cls.getName();
  13.229 -        /*
  13.230 -        if (n.startsWith("java.lang.")) {
  13.231 -            String nb = n.substring("java.lang.".length());
  13.232 -            if (nb.indexOf('.') < 0)  n = nb;
  13.233 -        } else if (n.indexOf('.') < 0) {
  13.234 -            n = "."+n;          // anonymous package
  13.235 -        }
  13.236 -        */
  13.237 -        sb.append(n);
  13.238 -        while (brackets > 0) {
  13.239 -            sb.append("[]");
  13.240 -            brackets--;
  13.241 -        }
  13.242 -    }
  13.243 -
  13.244      /// Queries which have to do with the bytecode architecture
  13.245  
  13.246      /** The number of JVM stack slots required to invoke a method
  13.247 @@ -690,14 +646,4 @@
  13.248      public String toMethodDescriptorString() {
  13.249          return BytecodeDescriptor.unparse(this);
  13.250      }
  13.251 -
  13.252 -    /** Temporary alias for toMethodDescriptorString; delete after M3. */
  13.253 -    public String toBytecodeString() {
  13.254 -        return toMethodDescriptorString();
  13.255 -    }
  13.256 -    /** Temporary alias for fromMethodDescriptorString; delete after M3. */
  13.257 -    public static MethodType fromBytecodeString(String descriptor, ClassLoader loader)
  13.258 -        throws IllegalArgumentException, TypeNotPresentException {
  13.259 -        return fromMethodDescriptorString(descriptor, loader);
  13.260 -    }
  13.261  }
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/share/classes/java/dyn/MutableCallSite.java	Tue Dec 21 18:45:45 2010 -0800
    14.3 @@ -0,0 +1,206 @@
    14.4 +/*
    14.5 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.25 + * or visit www.oracle.com if you need additional information or have any
   14.26 + * questions.
   14.27 + */
   14.28 +
   14.29 +package java.dyn;
   14.30 +
   14.31 +import sun.dyn.*;
   14.32 +import sun.dyn.empty.Empty;
   14.33 +import java.util.concurrent.atomic.AtomicInteger;
   14.34 +
   14.35 +/**
   14.36 + * A {@code MutableCallSite} is a {@link CallSite} whose target variable
   14.37 + * behaves like an ordinary field.
   14.38 + * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
   14.39 + * all calls to the site's current target.
   14.40 + * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
   14.41 + * also delegates each call to the site's current target.
   14.42 + * <p>
   14.43 + * Here is an example of a mutable call site which introduces a
   14.44 + * state variable into a method handle chain.
   14.45 + * <blockquote><pre>
   14.46 +MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
   14.47 +MethodHandle MH_name = name.dynamicInvoker();
   14.48 +MethodType MT_str2 = MethodType.methodType(String.class, String.class);
   14.49 +MethodHandle MH_upcase = MethodHandles.lookup()
   14.50 +    .findVirtual(String.class, "toUpperCase", MT_str2);
   14.51 +MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
   14.52 +name.setTarget(MethodHandles.constant(String.class, "Rocky"));
   14.53 +assertEquals("ROCKY", (String) worker1.invokeExact());
   14.54 +name.setTarget(MethodHandles.constant(String.class, "Fred"));
   14.55 +assertEquals("FRED", (String) worker1.invokeExact());
   14.56 +// (mutation can be continued indefinitely)
   14.57 + * </pre></blockquote>
   14.58 + * <p>
   14.59 + * The same call site may be used in several places at once.
   14.60 + * <blockquote><pre>
   14.61 +MethodHandle MH_dear = MethodHandles.lookup()
   14.62 +    .findVirtual(String.class, "concat", MT_str2).bindTo(", dear?");
   14.63 +MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
   14.64 +assertEquals("Fred, dear?", (String) worker2.invokeExact());
   14.65 +name.setTarget(MethodHandles.constant(String.class, "Wilma"));
   14.66 +assertEquals("WILMA", (String) worker1.invokeExact());
   14.67 +assertEquals("Wilma, dear?", (String) worker2.invokeExact());
   14.68 + * </pre></blockquote>
   14.69 + * <p>
   14.70 + * <em>Non-synchronization of target values:</em>
   14.71 + * A write to a mutable call site's target does not force other threads
   14.72 + * to become aware of the updated value.  Threads which do not perform
   14.73 + * suitable synchronization actions relative to the updated call site
   14.74 + * may cache the old target value and delay their use of the new target
   14.75 + * value indefinitely.
   14.76 + * (This is a normal consequence of the Java Memory Model as applied
   14.77 + * to object fields.)
   14.78 + * <p>
   14.79 + * The {@link #sync sync} operation provides a way to force threads
   14.80 + * to accept a new target value, even if there is no other synchronization.
   14.81 + * <p>
   14.82 + * For target values which will be frequently updated, consider using
   14.83 + * a {@linkplain VolatileCallSite volatile call site} instead.
   14.84 + * @author John Rose, JSR 292 EG
   14.85 + */
   14.86 +public class MutableCallSite extends CallSite {
   14.87 +    /**
   14.88 +     * Make a blank call site object with the given method type.
   14.89 +     * An initial target method is supplied which will throw
   14.90 +     * an {@link IllegalStateException} if called.
   14.91 +     * <p>
   14.92 +     * Before this {@code CallSite} object is returned from a bootstrap method,
   14.93 +     * it is usually provided with a more useful target method,
   14.94 +     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
   14.95 +     * @throws NullPointerException if the proposed type is null
   14.96 +     */
   14.97 +    public MutableCallSite(MethodType type) {
   14.98 +        super(type);
   14.99 +    }
  14.100 +
  14.101 +    /**
  14.102 +     * Make a blank call site object, possibly equipped with an initial target method handle.
  14.103 +     * @param target the method handle which will be the initial target of the call site
  14.104 +     * @throws NullPointerException if the proposed target is null
  14.105 +     */
  14.106 +    public MutableCallSite(MethodHandle target) {
  14.107 +        super(target);
  14.108 +    }
  14.109 +
  14.110 +    /**
  14.111 +     * Perform a synchronization operation on each call site in the given array,
  14.112 +     * forcing all other threads to throw away any cached values previously
  14.113 +     * loaded from the target of any of the call sites.
  14.114 +     * <p>
  14.115 +     * This operation does not reverse any calls that have already started
  14.116 +     * on an old target value.
  14.117 +     * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
  14.118 +     * <p>
  14.119 +     * The overall effect is to force all future readers of each call site's target
  14.120 +     * to accept the most recently stored value.
  14.121 +     * ("Most recently" is reckoned relative to the {@code sync} itself.)
  14.122 +     * Conversely, the {@code sync} call may block until all readers have
  14.123 +     * (somehow) decached all previous versions of each call site's target.
  14.124 +     * <p>
  14.125 +     * To avoid race conditions, calls to {@code setTarget} and {@code sync}
  14.126 +     * should generally be performed under some sort of mutual exclusion.
  14.127 +     * Note that reader threads may observe an updated target as early
  14.128 +     * as the {@code setTarget} call that install the value
  14.129 +     * (and before the {@code sync} that confirms the value).
  14.130 +     * On the other hand, reader threads may observe previous versions of
  14.131 +     * the target until the {@code sync} call returns
  14.132 +     * (and after the {@code setTarget} that attempts to convey the updated version).
  14.133 +     * <p>
  14.134 +     * In terms of the Java Memory Model, this operation performs a synchronization
  14.135 +     * action which is comparable in effect to the writing of a volatile variable
  14.136 +     * by the current thread, and an eventual volatile read by every other thread
  14.137 +     * that may access one of the affected call sites.
  14.138 +     * <p>
  14.139 +     * The following effects are apparent, for each individual call site {@code S}:
  14.140 +     * <ul>
  14.141 +     * <li>A new volatile variable {@code V} is created, and written by the current thread.
  14.142 +     *     As defined by the JMM, this write is a global synchronization event.
  14.143 +     * <li>As is normal with thread-local ordering of write events,
  14.144 +     *     every action already performed by the current thread is
  14.145 +     *     taken to happen before the volatile write to {@code V}.
  14.146 +     *     (In some implementations, this means that the current thread
  14.147 +     *     performs a global release operation.)
  14.148 +     * <li>Specifically, the write to the current target of {@code S} is
  14.149 +     *     taken to happen before the volatile write to {@code V}.
  14.150 +     * <li>The volatile write to {@code V} is placed
  14.151 +     *     (in an implementation specific manner)
  14.152 +     *     in the global synchronization order.
  14.153 +     * <li>Consider an arbitrary thread {@code T} (other than the current thread).
  14.154 +     *     If {@code T} executes a synchronization action {@code A}
  14.155 +     *     after the volatile write to {@code V} (in the global synchronization order),
  14.156 +     *     it is therefore required to see either the current target
  14.157 +     *     of {@code S}, or a later write to that target,
  14.158 +     *     if it executes a read on the target of {@code S}.
  14.159 +     *     (This constraint is called "synchronization-order consistency".)
  14.160 +     * <li>The JMM specifically allows optimizing compilers to elide
  14.161 +     *     reads or writes of variables that are known to be useless.
  14.162 +     *     Such elided reads and writes have no effect on the happens-before
  14.163 +     *     relation.  Regardless of this fact, the volatile {@code V}
  14.164 +     *     will not be elided, even though its written value is
  14.165 +     *     indeterminate and its read value is not used.
  14.166 +     * </ul>
  14.167 +     * Because of the last point, the implementation behaves as if a
  14.168 +     * volatile read of {@code V} were performed by {@code T}
  14.169 +     * immediately after its action {@code A}.  In the local ordering
  14.170 +     * of actions in {@code T}, this read happens before any future
  14.171 +     * read of the target of {@code S}.  It is as if the
  14.172 +     * implementation arbitrarily picked a read of {@code S}'s target
  14.173 +     * by {@code T}, and forced a read of {@code V} to precede it,
  14.174 +     * thereby ensuring communication of the new target value.
  14.175 +     * <p>
  14.176 +     * As long as the constraints of the Java Memory Model are obeyed,
  14.177 +     * implementations may delay the completion of a {@code sync}
  14.178 +     * operation while other threads ({@code T} above) continue to
  14.179 +     * use previous values of {@code S}'s target.
  14.180 +     * However, implementations are (as always) encouraged to avoid
  14.181 +     * livelock, and to eventually require all threads to take account
  14.182 +     * of the updated target.
  14.183 +     * <p>
  14.184 +     * This operation is likely to be expensive and should be used sparingly.
  14.185 +     * If possible, it should be buffered for batch processing on sets of call sites.
  14.186 +     * <p style="font-size:smaller;">
  14.187 +     * (This is a static method on a set of call sites, not a
  14.188 +     * virtual method on a single call site, for performance reasons.
  14.189 +     * Some implementations may incur a large fixed overhead cost
  14.190 +     * for processing one or more synchronization operations,
  14.191 +     * but a small incremental cost for each additional call site.
  14.192 +     * In any case, this operation is likely to be costly, since
  14.193 +     * other threads may have to be somehow interrupted
  14.194 +     * in order to make them notice the updated target value.
  14.195 +     * However, it may be observed that a single call to synchronize
  14.196 +     * several sites has the same formal effect as many calls,
  14.197 +     * each on just one of the sites.)
  14.198 +     * <p>
  14.199 +     * Simple implementations of {@code MutableCallSite} may use
  14.200 +     * a volatile variable for the target of a mutable call site.
  14.201 +     * In such an implementation, the {@code sync} method can be a no-op,
  14.202 +     * and yet it will conform to the JMM behavior documented above.
  14.203 +     */
  14.204 +    public static void sync(MutableCallSite[] sites) {
  14.205 +        STORE_BARRIER.lazySet(0);
  14.206 +        // FIXME: NYI
  14.207 +    }
  14.208 +    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
  14.209 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/share/classes/java/dyn/Switcher.java	Tue Dec 21 18:45:45 2010 -0800
    15.3 @@ -0,0 +1,130 @@
    15.4 +/*
    15.5 + * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   15.11 + * particular file as subject to the "Classpath" exception as provided
   15.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.25 + * or visit www.oracle.com if you need additional information or have any
   15.26 + * questions.
   15.27 + */
   15.28 +
   15.29 +package java.dyn;
   15.30 +
   15.31 +/**
   15.32 + * <p>
   15.33 + * A {@code Switcher} is an object which can publish state transitions to other threads.
   15.34 + * A switcher is initially in the <em>valid</em> state, but may at any time be
   15.35 + * changed to the <em>invalid</em> state.  Invalidation cannot be reversed.
   15.36 + * <p>
   15.37 + * A single switcher may be used to create any number of guarded method handle pairs.
   15.38 + * Each guarded pair is wrapped in a new method handle {@code M},
   15.39 + * which is permanently associated with the switcher that created it.
   15.40 + * Each pair consists of a target {@code T} and a fallback {@code F}.
   15.41 + * While the switcher is valid, invocations to {@code M} are delegated to {@code T}.
   15.42 + * After it is invalidated, invocations are delegated to {@code F}.
   15.43 + * <p>
   15.44 + * Invalidation is global and immediate, as if the switcher contained a
   15.45 + * volatile boolean variable consulted on every call to {@code M}.
   15.46 + * The invalidation is also permanent, which means the switcher
   15.47 + * can change state only once.
   15.48 + * <p>
   15.49 + * Here is an example of a switcher in action:
   15.50 + * <blockquote><pre>
   15.51 +MethodType MT_str2 = MethodType.methodType(String.class, String.class);
   15.52 +MethodHandle MH_strcat = MethodHandles.lookup()
   15.53 +    .findVirtual(String.class, "concat", MT_str2);
   15.54 +Switcher switcher = new Switcher();
   15.55 +// the following steps may be repeated to re-use the same switcher:
   15.56 +MethodHandle worker1 = strcat;
   15.57 +MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
   15.58 +MethodHandle worker = switcher.guardWithTest(worker1, worker2);
   15.59 +assertEquals("method", (String) worker.invokeExact("met", "hod"));
   15.60 +switcher.invalidate();
   15.61 +assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
   15.62 + * </pre></blockquote>
   15.63 + * <p>
   15.64 + * <em>Implementation Note:</em>
   15.65 + * A switcher behaves as if implemented on top of {@link MutableCallSite},
   15.66 + * approximately as follows:
   15.67 + * <blockquote><pre>
   15.68 +public class Switcher {
   15.69 +  private static final MethodHandle
   15.70 +    K_true  = MethodHandles.constant(boolean.class, true),
   15.71 +    K_false = MethodHandles.constant(boolean.class, false);
   15.72 +  private final MutableCallSite mcs;
   15.73 +  private final MethodHandle mcsInvoker;
   15.74 +  public Switcher() {
   15.75 +    this.mcs = new MutableCallSite(K_true);
   15.76 +    this.mcsInvoker = mcs.dynamicInvoker();
   15.77 +  }
   15.78 +  public MethodHandle guardWithTest(
   15.79 +                MethodHandle target, MethodHandle fallback) {
   15.80 +    // Note:  mcsInvoker is of type boolean().
   15.81 +    // Target and fallback may take any arguments, but must have the same type.
   15.82 +    return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
   15.83 +  }
   15.84 +  public static void invalidateAll(Switcher[] switchers) {
   15.85 +    List<MutableCallSite> mcss = new ArrayList<>();
   15.86 +    for (Switcher s : switchers)  mcss.add(s.mcs);
   15.87 +    for (MutableCallSite mcs : mcss)  mcs.setTarget(K_false);
   15.88 +    MutableCallSite.sync(mcss.toArray(new MutableCallSite[0]));
   15.89 +  }
   15.90 +}
   15.91 + * </pre></blockquote>
   15.92 + * @author Remi Forax, JSR 292 EG
   15.93 + */
   15.94 +public class Switcher {
   15.95 +    private static final MethodHandle
   15.96 +        K_true  = MethodHandles.constant(boolean.class, true),
   15.97 +        K_false = MethodHandles.constant(boolean.class, false);
   15.98 +
   15.99 +    private final MutableCallSite mcs;
  15.100 +    private final MethodHandle mcsInvoker;
  15.101 +
  15.102 +    /** Create a switcher. */
  15.103 +    public Switcher() {
  15.104 +        this.mcs = new MutableCallSite(K_true);
  15.105 +        this.mcsInvoker = mcs.dynamicInvoker();
  15.106 +    }
  15.107 +
  15.108 +    /**
  15.109 +     * Return a method handle which always delegates either to the target or the fallback.
  15.110 +     * The method handle will delegate to the target exactly as long as the switcher is valid.
  15.111 +     * After that, it will permanently delegate to the fallback.
  15.112 +     * <p>
  15.113 +     * The target and fallback must be of exactly the same method type,
  15.114 +     * and the resulting combined method handle will also be of this type.
  15.115 +     * @see MethodHandles#guardWithTest
  15.116 +     */
  15.117 +    public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
  15.118 +        if (mcs.getTarget() == K_false)
  15.119 +            return fallback;  // already invalid
  15.120 +        return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
  15.121 +    }
  15.122 +
  15.123 +    /** Set all of the given switchers into the invalid state. */
  15.124 +    public static void invalidateAll(Switcher[] switchers) {
  15.125 +        MutableCallSite[] sites = new MutableCallSite[switchers.length];
  15.126 +        int fillp = 0;
  15.127 +        for (Switcher switcher : switchers) {
  15.128 +            sites[fillp++] = switcher.mcs;
  15.129 +            switcher.mcs.setTarget(K_false);
  15.130 +        }
  15.131 +        MutableCallSite.sync(sites);
  15.132 +    }
  15.133 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/share/classes/java/dyn/VolatileCallSite.java	Tue Dec 21 18:45:45 2010 -0800
    16.3 @@ -0,0 +1,79 @@
    16.4 +/*
    16.5 + * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.25 + * or visit www.oracle.com if you need additional information or have any
   16.26 + * questions.
   16.27 + */
   16.28 +
   16.29 +package java.dyn;
   16.30 +
   16.31 +import java.util.List;
   16.32 +
   16.33 +/**
   16.34 + * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
   16.35 + * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
   16.36 + * to its call site target immediately, even if the update occurs in another thread.
   16.37 + * There may be a performance penalty for such tight coupling between threads.
   16.38 + * <p>
   16.39 + * Unlike {@code MutableCallSite}, there is no
   16.40 + * {@linkplain MutableCallSite#sync sync operation} on volatile
   16.41 + * call sites, since every write to a volatile variable is implicitly
   16.42 + * synchronized with reader threads.
   16.43 + * <p>
   16.44 + * In other respects, a {@code VolatileCallSite} is interchangeable
   16.45 + * with {@code MutableCallSite}.
   16.46 + * @see MutableCallSite
   16.47 + * @author John Rose, JSR 292 EG
   16.48 + */
   16.49 +public class VolatileCallSite extends CallSite {
   16.50 +    /** Create a call site with a volatile target.
   16.51 +     *  The initial target is set to a method handle
   16.52 +     *  of the given type which will throw {@code IllegalStateException}.
   16.53 +     * @throws NullPointerException if the proposed type is null
   16.54 +     */
   16.55 +    public VolatileCallSite(MethodType type) {
   16.56 +        super(type);
   16.57 +    }
   16.58 +
   16.59 +    /** Create a call site with a volatile target.
   16.60 +     *  The target is set to the given value.
   16.61 +     * @throws NullPointerException if the proposed target is null
   16.62 +     */
   16.63 +    public VolatileCallSite(MethodHandle target) {
   16.64 +        super(target);
   16.65 +    }
   16.66 +
   16.67 +    /** Internal override to nominally final getTarget. */
   16.68 +    @Override
   16.69 +    MethodHandle getTarget0() {
   16.70 +        return getTargetVolatile();
   16.71 +    }
   16.72 +
   16.73 +    /**
   16.74 +     * Set the target method of this call site, as a volatile variable.
   16.75 +     * Has the same effect as {@link CallSite#setTarget CallSite.setTarget}, with the additional
   16.76 +     * effects associated with volatiles, in the Java Memory Model.
   16.77 +     */
   16.78 +    @Override public void setTarget(MethodHandle newTarget) {
   16.79 +        checkTargetChange(getTargetVolatile(), newTarget);
   16.80 +        setTargetVolatile(newTarget);
   16.81 +    }
   16.82 +}
    17.1 --- a/src/share/classes/java/dyn/package-info.java	Tue Dec 21 15:27:55 2010 -0800
    17.2 +++ b/src/share/classes/java/dyn/package-info.java	Tue Dec 21 18:45:45 2010 -0800
    17.3 @@ -24,7 +24,6 @@
    17.4   */
    17.5  
    17.6  /**
    17.7 - * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    17.8   * This package contains dynamic language support provided directly by
    17.9   * the Java core class libraries and virtual machine.
   17.10   * <p>
   17.11 @@ -42,13 +41,6 @@
   17.12   * argument and return value conversions are applied.
   17.13   * </li>
   17.14   *
   17.15 - * <li>In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
   17.16 - * any static method invocation, of any name and any signature.
   17.17 - * But instead of emitting
   17.18 - * an {@code invokestatic} instruction for such a call, the Java compiler emits
   17.19 - * an {@code invokedynamic} instruction with the given name and signature.
   17.20 - * </li>
   17.21 - *
   17.22   * <li>The JVM bytecode format supports immediate constants of
   17.23   * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
   17.24   * </li>
   17.25 @@ -56,51 +48,68 @@
   17.26   *
   17.27   * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
   17.28   * <em>The following low-level information is presented here as a preview of
   17.29 - * changes being made to the Java Virtual Machine specification for JSR 292.</em>
   17.30 + * changes being made to the Java Virtual Machine specification for JSR 292.
   17.31 + * This information will be incorporated in a future version of the JVM specification.</em>
   17.32   *
   17.33 - * <h3>{@code invokedynamic} instruction format</h3>
   17.34 + * <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3>
   17.35   * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
   17.36   * The first byte is the opcode 186 (hexadecimal {@code BA}).
   17.37   * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
   17.38   * The final two bytes are reserved for future use and required to be zero.
   17.39   * The constant pool reference of an {@code invokedynamic} instruction is to a entry
   17.40 - * with tag {@code CONSTANT_InvokeDynamic} (decimal 17).  See below for its format.
   17.41 - * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
   17.42 - * the dynamic invocation name, and the argument types and return type of the call.
   17.43 + * with tag {@code CONSTANT_InvokeDynamic} (decimal 18).  See below for its format.
   17.44 + * (The tag value 17 is also temporarily allowed.  See below.)
   17.45 + * The entry specifies the following information:
   17.46 + * <ul>
   17.47 + * <li>a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)</li>
   17.48 + * <li>the dynamic invocation name (a UTF8 string)</li>
   17.49 + * <li>the argument and return types of the call (encoded as a signature in a UTF8 string)</li>
   17.50 + * <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
   17.51 + * </ul>
   17.52   * <p>
   17.53   * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
   17.54   * Multiple instances of an {@code invokedynamic} instruction can share a single
   17.55   * {@code CONSTANT_InvokeDynamic} entry.
   17.56   * In any case, distinct call sites always have distinct linkage state.
   17.57   * <p>
   17.58 - * Moreover, for the purpose of distinguishing dynamic call sites,
   17.59 - * the JVM is allowed (but not required) to make internal copies
   17.60 - * of {@code invokedynamic} instructions, each one
   17.61 - * constituting a separate dynamic call site with its own linkage state.
   17.62 - * Such copying, if it occurs, cannot be observed except indirectly via
   17.63 - * execution of bootstrap methods and target methods.
   17.64 - * <p>
   17.65   * A dynamic call site is originally in an unlinked state.  In this state, there is
   17.66   * no target method for the call site to invoke.
   17.67   * A dynamic call site is linked by means of a bootstrap method,
   17.68   * as <a href="#bsm">described below</a>.
   17.69 + *
   17.70 + * <p style="font-size:smaller;">
   17.71 + * (Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
   17.72 + * instead of a {@code CONSTANT_InvokeDynamic}.  In earlier, obsolete versions of this API, the
   17.73 + * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)
   17.74 + *
   17.75 + * <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
   17.76 + * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
   17.77 + * it must contain exactly four more bytes after the tag.
   17.78 + * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
   17.79 + * The first pair of bytes after the tag must be an index into a side table called the
   17.80 + * <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
   17.81 + * attribute as <a href="#bsmattr">described below</a>.
   17.82 + * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
   17.83 + * This table is not part of the constant pool.  Instead, it is stored
   17.84 + * in a class attribute named {@code BootstrapMethods}, described below.
   17.85   * <p>
   17.86 - * <em>(Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
   17.87 - * instead of a {@code CONSTANT_InvokeDynamic}.  In earlier, obsolete versions of this API, the
   17.88 - * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)</em>
   17.89 - *
   17.90 - * <h3>constant pool entries for {@code invokedynamic} instructions</h3>
   17.91 - * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
   17.92 - * it must contain exactly four more bytes.
   17.93 - * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
   17.94 - * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
   17.95   * The first index specifies a bootstrap method used by the associated dynamic call sites.
   17.96   * The second index specifies the method name, argument types, and return type of the dynamic call site.
   17.97   * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
   17.98 - * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
   17.99 - * is replaced by a bootstrap method reference.
  17.100 + * except that the bootstrap method specifier reference replaces
  17.101 + * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
  17.102 + * <p>
  17.103 + * Some older JVMs may allow an older constant pool entry tag of decimal 17.
  17.104 + * The format and behavior of a constant pool entry with this tag is identical to
  17.105 + * an entry with a tag of decimal 18, except that the first index refers directly
  17.106 + * to a {@code CONSTANT_MethodHandle} to use as the bootstrap method.
  17.107 + * This format does not require the bootstrap method table.
  17.108   *
  17.109 - * <h3>constant pool entries for {@code MethodType}s</h3>
  17.110 + * <p style="font-size:smaller;">
  17.111 + * <em>(Note: The Proposed Final Draft of this specification is likely to support
  17.112 + * only the tag 18, not the tag 17.)</em>
  17.113 + *
  17.114 + * <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.dyn.MethodType method types}</h3>
  17.115   * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
  17.116   * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
  17.117   * entry which represents a method type signature.
  17.118 @@ -113,7 +122,7 @@
  17.119   * Access checking and error reporting is performed exactly as it is for
  17.120   * references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
  17.121   *
  17.122 - * <h3>constant pool entries for {@code MethodHandle}s</h3>
  17.123 + * <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.dyn.MethodHandle method handles}</h3>
  17.124   * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
  17.125   * it must contain exactly three more bytes.  The first byte after the tag is a subtag
  17.126   * value which must be in the range 1 through 9, and the last two must be an index to a
  17.127 @@ -129,7 +138,7 @@
  17.128   * <p>
  17.129   * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
  17.130   * the {@code Class} or {@code MethodType} object which reifies the field or method's
  17.131 - * type is created.  Any classes mentioned in this reificaiton will be loaded if necessary,
  17.132 + * type is created.  Any classes mentioned in this reification will be loaded if necessary,
  17.133   * but not initialized, and access checking and error reporting performed as usual.
  17.134   * <p>
  17.135   * The method handle itself will have a type and behavior determined by the subtag as follows:
  17.136 @@ -148,16 +157,45 @@
  17.137   * </table>
  17.138   * </code>
  17.139   * <p>
  17.140 - * The special names {@code <init>} and {@code <clinit>} are not allowed except for subtag 8 as shown.
  17.141 + * The special name {@code <clinit>} is not allowed.
  17.142 + * The special name {@code <init>} is not allowed except for subtag 8 as shown.
  17.143   * <p>
  17.144 - * The verifier applies the same access checks and restrictions for these references as for the hypothetical
  17.145 + * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
  17.146   * bytecode instructions specified in the last column of the table.  In particular, method handles to
  17.147   * private and protected members can be created in exactly those classes for which the corresponding
  17.148   * normal accesses are legal.
  17.149   * <p>
  17.150 - * None of these constant types force class initialization.
  17.151 - * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
  17.152 + * A constant may refer to a method or constructor with the {@code varargs}
  17.153 + * bit (hexadecimal {@code 80}) set in its modifier bitmask.
  17.154 + * The method handle constant produced for such a method behaves the same
  17.155 + * as if the {@code varargs} bit were not set.
  17.156 + * The argument-collecting behavior of {@code varargs} can be emulated by
  17.157 + * adapting the method handle constant with
  17.158 + * {@link java.dyn.MethodHandle#asCollector asCollector}.
  17.159 + * There is no provision for doing this automatically.
  17.160 + * <p>
  17.161 + * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
  17.162 + * resolve class names, they do not force class initialization.
  17.163 + * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
  17.164   * may force class initialization on their first invocation, just like the corresponding bytecodes.
  17.165 + * <p>
  17.166 + * The rules of section 5.4.3 of the
  17.167 + * <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#73492">JVM Specification</a>
  17.168 + * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
  17.169 + * and {@code CONSTANT_InvokeDynamic} constants,
  17.170 + * by the execution of {@code invokedynamic} and {@code ldc} instructions.
  17.171 + * (Roughly speaking, this means that every use of a constant pool entry
  17.172 + * must lead to the same outcome.
  17.173 + * If the resoultion succeeds, the same object reference is produced
  17.174 + * by every subsequent execution of the same instruction.
  17.175 + * If the resolution of the constant causes an error to occur,
  17.176 + * the same error will be re-thrown on every subsequent attempt
  17.177 + * to use this particular constant.)
  17.178 + * <p>
  17.179 + * Constants created by the resolution of these constant pool types are not necessarily
  17.180 + * interned.  Except for {@link CONSTANT_Class} and {@link CONSTANT_String} entries,
  17.181 + * two distinct constant pool entries might not resolve to the same reference
  17.182 + * even if they contain the same symbolic reference.
  17.183   *
  17.184   * <h2><a name="bsm"></a>Bootstrap Methods</h2>
  17.185   * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
  17.186 @@ -181,24 +219,36 @@
  17.187   * call site execution.
  17.188   * Linkage does not trigger class initialization.
  17.189   * <p>
  17.190 - * Next, the bootstrap method call is started, with four values being stacked:
  17.191 + * Next, the bootstrap method call is started, with four or five values being stacked:
  17.192   * <ul>
  17.193   * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
  17.194 - * <li>a {@code Class}, the <em>caller class</em> in which dynamic call site occurs </li>
  17.195 + * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
  17.196   * <li>a {@code String}, the method name mentioned in the call site </li>
  17.197   * <li>a {@code MethodType}, the resolved type signature of the call </li>
  17.198 + * <li>optionally, a single object representing one or more <a href="#args">additional static arguments</a> </li>
  17.199   * </ul>
  17.200   * The method handle is then applied to the other values as if by
  17.201 - * {@linkplain java.dyn.MethodHandle#invokeGeneric the <code>invokeGeneric</code> method}.
  17.202 - * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
  17.203 - * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
  17.204 - * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
  17.205 - * is then called on the returned value.  The result of that second
  17.206 - * call is the {@code MethodHandle} which becomes the
  17.207 - * permanent binding for the dynamic call site.
  17.208 - * That method handle's type must be exactly equal to the type
  17.209 + * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}.
  17.210 + * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass).
  17.211 + * The type of the call site's target must be exactly equal to the type
  17.212   * derived from the dynamic call site signature and passed to
  17.213   * the bootstrap method.
  17.214 + * The call site then becomes permanently linked to the dynamic call site.
  17.215 + * <p>
  17.216 + * As long as each bootstrap method can be correctly invoked
  17.217 + * by <code>invokeGeneric</code>, its detailed type is arbitrary.
  17.218 + * For example, the first argument could be {@code Object}
  17.219 + * instead of {@code MethodHandles.Lookup}, and the return type
  17.220 + * could also be {@code Object} instead of {@code CallSite}.
  17.221 + * <p>
  17.222 + * As with any method handle constant, a {@code varargs} modifier bit
  17.223 + * on the bootstrap method is ignored.
  17.224 + * <p>
  17.225 + * Note that the first argument of the bootstrap method cannot be
  17.226 + * a simple {@code Class} reference.  (This is a change from earlier
  17.227 + * versions of this specification.  If the caller class is needed,
  17.228 + * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
  17.229 + * from the {@code Lookup} object.)
  17.230   * <p>
  17.231   * After resolution, the linkage process may fail in a variety of ways.
  17.232   * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
  17.233 @@ -206,81 +256,209 @@
  17.234   * site execution.
  17.235   * The following circumstances will cause this:
  17.236   * <ul>
  17.237 + * <li>the index to the bootstrap method specifier is out of range </li>
  17.238 + * <li>the bootstrap method cannot be resolved </li>
  17.239 + * <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
  17.240 + * <li>a static argument to the bootstrap method cannot be resolved
  17.241 + *     (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
  17.242 + *     or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
  17.243 + * <li>the bootstrap method has the wrong arity,
  17.244 + *     causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li>
  17.245 + * <li>the bootstrap method has a wrong argument or return type </li>
  17.246   * <li>the bootstrap method invocation completes abnormally </li>
  17.247   * <li>the result from the bootstrap invocation is not a reference to
  17.248 - *     an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider} </li>
  17.249 - * <li>the call to {@code asMethodHandle} completes abnormally </li>
  17.250 - * <li>the call to {@code asMethodHandle} fails to return a reference to
  17.251 - *     an object of type {@link java.dyn.MethodHandle MethodHandle} </li>
  17.252 - * <li>the method handle produced by {@code asMethodHandle} does not have
  17.253 + *     an object of type {@link java.dyn.CallSite CallSite} </li>
  17.254 + * <li>the target of the {@code CallSite} does not have a target of
  17.255   *     the expected {@code MethodType} </li>
  17.256   * </ul>
  17.257 - * <h3>timing of linkage</h3>
  17.258 + *
  17.259 + * <h3><a name="linktime"></a>timing of linkage</h3>
  17.260   * A dynamic call site is linked just before its first execution.
  17.261   * The bootstrap method call implementing the linkage occurs within
  17.262   * a thread that is attempting a first execution.
  17.263   * <p>
  17.264 - * If there are several such threads, the JVM picks one thread
  17.265 - * and runs the bootstrap method while the others wait for the
  17.266 - * invocation to terminate normally or abnormally.
  17.267 - * <p>
  17.268 - * After a bootstrap method is called and a method handle target
  17.269 - * successfully extracted, the JVM attempts to link the instruction
  17.270 - * being executed to the target method handle.
  17.271 - * This may fail if there has been intervening linkage
  17.272 - * or invalidation event for the same instruction.
  17.273 - * If such a failure occurs, the dynamic call site must be
  17.274 - * re-executed from the beginning, either re-linking it
  17.275 - * (if it has been invalidated) or invoking the target
  17.276 - * (if it the instruction has been linked by some other means).
  17.277 - * <p>
  17.278 - * If the instruction is linked successfully, the target method
  17.279 - * handle is invoked to complete the instruction execution.
  17.280 - * The state of linkage continues until the method containing the
  17.281 - * dynamic call site is garbage collected, or the dynamic call site
  17.282 - * is invalidated by an explicit request,
  17.283 - * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
  17.284 + * If there are several such threads, the bootstrap method may be
  17.285 + * invoked in several threads concurrently.
  17.286 + * Therefore, bootstrap methods which access global application
  17.287 + * data must take the usual precautions against race conditions.
  17.288 + * In any case, every {@code invokedynamic} instruction is either
  17.289 + * unlinked or linked to a unique {@code CallSite} object.
  17.290   * <p>
  17.291   * In an application which requires dynamic call sites with individually
  17.292   * mutable behaviors, their bootstrap methods should produce distinct
  17.293   * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
  17.294 - * <p>
  17.295 - * If a class containing {@code invokedynamic} instructions
  17.296 - * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
  17.297 - * subsequent execution of those {@code invokedynamic} instructions
  17.298 - * will require linking.
  17.299 - * It is as if they had never been executed in the first place.
  17.300 - * (However, invalidation does not cause constant pool entries to be
  17.301 - * resolved a second time.)
  17.302 - * <p>
  17.303 - * Invalidation events and bootstrap method calls for a particular
  17.304 - * dynamic call site are globally ordered relative to each other.
  17.305 - * When an invokedynamic instruction is invalidated, if there is
  17.306 - * simultaneously a bootstrap method invocation in process
  17.307 - * (in the same thread or a different thread), the result
  17.308 - * eventually returned must not be used to link the call site.
  17.309 - * Put another way, when a call site is invalidated, its
  17.310 - * subsequent linkage (if any) must be performed by a bootstrap method
  17.311 - * call initiated after the invalidation occurred.
  17.312 + * Alternatively, an application can link a single {@code CallSite} object
  17.313 + * to several {@code invokedynamic} instructions, in which case
  17.314 + * a change to the target method will become visible at each of
  17.315 + * the instructions.
  17.316   * <p>
  17.317   * If several threads simultaneously execute a bootstrap method for a single dynamic
  17.318 - * call site, the JVM must choose one target object and installs it visibly to
  17.319 + * call site, the JVM must choose one {@code CallSite} object and install it visibly to
  17.320   * all threads.  Any other bootstrap method calls are allowed to complete, but their
  17.321   * results are ignored, and their dynamic call site invocations proceed with the originally
  17.322   * chosen target object.
  17.323 + *
  17.324 + * <p style="font-size:smaller;">
  17.325 + * (Historic Note: Unlike some previous versions of this specification,
  17.326 + * these rules do not enable the JVM to duplicate dynamic call sites,
  17.327 + * or to issue &ldquo;causeless&rdquo; bootstrap method calls.
  17.328 + * Every dynamic call site transitions at most once from unlinked to linked,
  17.329 + * just before its first invocation.)
  17.330 + *
  17.331 + * <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
  17.332 + * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
  17.333 + * a bootstrap method specifier; all such specifiers are contained in a separate array.
  17.334 + * This array is defined by a class attribute named {@code BootstrapMethods}.
  17.335 + * The body of this attribute consists of a sequence of byte pairs, all interpreted as
  17.336 + * as 16-bit counts or constant pool indexes, in the {@code u2} format.
  17.337 + * The attribute body starts with a count of bootstrap method specifiers,
  17.338 + * which is immediately followed by the sequence of specifiers.
  17.339   * <p>
  17.340 - * The JVM is free to duplicate dynamic call sites.
  17.341 - * This means that, even if a class contains just one {@code invokedynamic}
  17.342 - * instruction, its bootstrap method may be executed several times,
  17.343 - * once for each duplicate.  Thus, bootstrap method code should not
  17.344 - * assume an exclusive one-to-one correspondence between particular occurrences
  17.345 - * of {@code invokedynamic} bytecodes in class files and linkage events.
  17.346 + * Each bootstrap method specifier contains an index to a
  17.347 + * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
  17.348 + * method itself.
  17.349 + * This is followed by a count, and then a sequence (perhaps empty) of
  17.350 + * indexes to <a href="#args">additional static arguments</a>
  17.351 + * for the bootstrap method.
  17.352   * <p>
  17.353 - * In principle, each individual execution of an {@code invokedynamic}
  17.354 - * instruction could be deemed (by a conforming implementation) to be a separate
  17.355 - * duplicate, requiring its own execution of the bootstrap method.
  17.356 - * However, implementations are expected to perform code duplication
  17.357 - * (if at all) in order to improve performance, not make it worse.
  17.358 + * During class loading, the verifier must check the structure of the
  17.359 + * {@code BootstrapMethods} attribute.  In particular, each constant
  17.360 + * pool index must be of the correct type.  A bootstrap method index
  17.361 + * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
  17.362 + * Every other index must refer to a valid operand of an
  17.363 + * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
  17.364 + *
  17.365 + * <h3><a name="args">static arguments to the bootstrap method</h3>
  17.366 + * An {@code invokedynamic} instruction specifies at least three arguments
  17.367 + * to pass to its bootstrap method:
  17.368 + * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object},
  17.369 + * the name (extracted from the {@code CONSTANT_NameAndType} entry),
  17.370 + * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
  17.371 + * The {@code invokedynamic} instruction may specify additional metadata values
  17.372 + * to pass to its bootstrap method.
  17.373 + * Collectively, these values are called <em>static arguments</em> to the
  17.374 + * {@code invokedynamic} instruction, because they are used once at link
  17.375 + * time to determine the instruction's behavior on subsequent sets of
  17.376 + * <em>dynamic arguments</em>.
  17.377 + * <p>
  17.378 + * Static arguments are used to communicate application-specific meta-data
  17.379 + * to the bootstrap method.
  17.380 + * Drawn from the constant pool, they may include references to classes, method handles,
  17.381 + * strings, or numeric data that may be relevant to the task of linking that particular call site.
  17.382 + * <p>
  17.383 + * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
  17.384 + * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
  17.385 + * reference to the indexed value in the constant pool.
  17.386 + * If the value is a primitive type, it is converted to a reference by boxing conversion.
  17.387 + * The valid constant pool entries are listed in this table:
  17.388 + * <code>
  17.389 + * <table border=1 cellpadding=5 summary="Static argument types">
  17.390 + * <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
  17.391 + * <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
  17.392 + * <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
  17.393 + * <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
  17.394 + * <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
  17.395 + * <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
  17.396 + * <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
  17.397 + * <tr><td>CONSTANT_MethodHandle</td><td><code>java.dyn.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
  17.398 + * <tr><td>CONSTANT_MethodType</td><td><code>java.dyn.MethodType</code></td><td>the indexed method type constant</td></tr>
  17.399 + * </table>
  17.400 + * </code>
  17.401 + * <p>
  17.402 + * If a given {@code invokedynamic} instruction specifies no static arguments,
  17.403 + * the instruction's bootstrap method will be invoked on three arguments,
  17.404 + * conveying the instruction's caller class, name, and method type.
  17.405 + * If the {@code invokedynamic} instruction specifies one or more static arguments,
  17.406 + * a fourth argument will be passed to the bootstrap argument,
  17.407 + * either an {@code Object} reference to the sole extra argument (if there is one)
  17.408 + * or an {@code Object} array of references to all the arguments (if there are two or more),
  17.409 + * as if the bootstrap method is a variable-arity method.
  17.410 + * <code>
  17.411 + * <table border=1 cellpadding=5 summary="Static argument types">
  17.412 + * <tr><th>N</th><th>sample bootstrap method</th></tr>
  17.413 + * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
  17.414 + * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
  17.415 + * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
  17.416 + * </table>
  17.417 + * </code>
  17.418 + * <p>
  17.419 + * The argument and return types listed here are used by the {@code invokeGeneric}
  17.420 + * call to the bootstrap method.
  17.421 + * As noted above, the actual method type of the bootstrap method can vary.
  17.422 + * For example, the fourth argument could be {@code MethodHandle},
  17.423 + * if that is the type of the corresponding constant in
  17.424 + * the {@code CONSTANT_InvokeDynamic} entry.
  17.425 + * In that case, the {@code invokeGeneric} call will pass the extra method handle
  17.426 + * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
  17.427 + * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
  17.428 + * (If a string constant were passed instead, by badly generated code, that cast would then fail.)
  17.429 + * <p>
  17.430 + * If the fourth argument is an array, the array element type must be {@code Object},
  17.431 + * since object arrays (as produced by the JVM at this point) cannot be converted
  17.432 + * to other array types.
  17.433 + * <p>
  17.434 + * If an array is provided, it will appear to be freshly allocated.
  17.435 + * That is, the same array will not appear to two bootstrap method calls.
  17.436 + * <p>
  17.437 + * Extra bootstrap method arguments are intended to allow language implementors
  17.438 + * to safely and compactly encode metadata.
  17.439 + * In principle, the name and extra arguments are redundant,
  17.440 + * since each call site could be given its own unique bootstrap method.
  17.441 + * Such a practice is likely to produce large class files and constant pools.
  17.442 + *
  17.443 + * <p style="font-size:smaller;">
  17.444 + * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  17.445 + * (Usage Note: There is no mechanism for specifying five or more positional arguments to the bootstrap method.
  17.446 + * If there are two or more arguments, the Java code of the bootstrap method is required to extract them from
  17.447 + * a varargs-style object array.
  17.448 + * This design uses varargs because it anticipates some use cases where bootstrap arguments
  17.449 + * contribute components of variable-length structures, such as virtual function tables
  17.450 + * or interpreter token streams.
  17.451 + * Such parameters would be awkward or impossible to manage if represented
  17.452 + * as normal positional method arguments,
  17.453 + * since there would need to be one Java method per length.
  17.454 + * On balance, leaving out the varargs feature would cause more trouble to users than keeping it.
  17.455 + * Also, this design allows bootstrap methods to be called in a limited JVM stack depth.
  17.456 + * At both the user and JVM level, the difference between varargs and non-varargs
  17.457 + * calling sequences can easily be bridged via the
  17.458 + * {@link java.dyn.MethodHandle#asSpreader asSpreader}
  17.459 + * and {@link java.dyn.MethodHandle#asSpreader asCollector} methods.)
  17.460 + *
  17.461 + * <h2><a name="structs"></a>Structure Summary</h2>
  17.462 + * <blockquote><pre>// summary of constant and attribute structures
  17.463 +struct CONSTANT_MethodHandle_info {
  17.464 +  u1 tag = 15;
  17.465 +  u1 reference_kind;       // 1..8 (one of REF_invokeVirtual, etc.)
  17.466 +  u2 reference_index;      // index to CONSTANT_Fieldref or *Methodref
  17.467 +}
  17.468 +struct CONSTANT_MethodType_info {
  17.469 +  u1 tag = 16;
  17.470 +  u2 descriptor_index;    // index to CONSTANT_Utf8, as in NameAndType
  17.471 +}
  17.472 +struct CONSTANT_InvokeDynamic_17_info {
  17.473 +  u1 tag = 17;
  17.474 +  u2 bootstrap_method_index;   // index to CONSTANT_MethodHandle
  17.475 +  u2 name_and_type_index;      // same as for CONSTANT_Methodref, etc.
  17.476 +}
  17.477 +struct CONSTANT_InvokeDynamic_info {
  17.478 +  u1 tag = 18;
  17.479 +  u2 bootstrap_method_attr_index;  // index into BootstrapMethods_attr
  17.480 +  u2 name_and_type_index;          // index to CONSTANT_NameAndType, as in Methodref
  17.481 +}
  17.482 +struct BootstrapMethods_attr {
  17.483 + u2 name;  // CONSTANT_Utf8 = "BootstrapMethods"
  17.484 + u4 size;
  17.485 + u2 bootstrap_method_count;
  17.486 + struct bootstrap_method_specifier {
  17.487 +   u2 bootstrap_method_ref;  // index to CONSTANT_MethodHandle
  17.488 +   u2 bootstrap_argument_count;
  17.489 +   u2 bootstrap_arguments[bootstrap_argument_count];  // constant pool indexes
  17.490 + } bootstrap_methods[bootstrap_method_count];
  17.491 +}
  17.492 + * </pre></blockquote>
  17.493 + * <p>
  17.494 + * <em>Note: The Proposed Final Draft of JSR 292 may remove the constant tag 17,
  17.495 + * for the sake of simplicity.</em>
  17.496   *
  17.497   * @author John Rose, JSR 292 EG
  17.498   */
    18.1 --- a/src/share/classes/sun/dyn/AdapterMethodHandle.java	Tue Dec 21 15:27:55 2010 -0800
    18.2 +++ b/src/share/classes/sun/dyn/AdapterMethodHandle.java	Tue Dec 21 18:45:45 2010 -0800
    18.3 @@ -478,6 +478,39 @@
    18.4          return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
    18.5      }
    18.6  
    18.7 +    static MethodHandle makeTypeHandler(Access token,
    18.8 +                MethodHandle target, MethodHandle typeHandler) {
    18.9 +        Access.check(token);
   18.10 +        return new WithTypeHandler(target, typeHandler);
   18.11 +    }
   18.12 +
   18.13 +    static class WithTypeHandler extends AdapterMethodHandle {
   18.14 +        final MethodHandle target, typeHandler;
   18.15 +        WithTypeHandler(MethodHandle target, MethodHandle typeHandler) {
   18.16 +            super(target, target.type(), makeConv(OP_RETYPE_ONLY));
   18.17 +            this.target = target;
   18.18 +            this.typeHandler = typeHandler.asType(TYPE_HANDLER_TYPE);
   18.19 +        }
   18.20 +
   18.21 +        public MethodHandle asType(MethodType newType) {
   18.22 +            if (this.type() == newType)
   18.23 +                return this;
   18.24 +            try {
   18.25 +                MethodHandle retyped = (MethodHandle) typeHandler.invokeExact(target, newType);
   18.26 +                // Contract:  Must return the desired type, or throw WMT
   18.27 +                if (retyped.type() != newType)
   18.28 +                    throw new WrongMethodTypeException(retyped.toString());
   18.29 +                return retyped;
   18.30 +            } catch (Throwable ex) {
   18.31 +                if (ex instanceof Error)  throw (Error)ex;
   18.32 +                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
   18.33 +                throw new RuntimeException(ex);
   18.34 +            }
   18.35 +        }
   18.36 +        private static final MethodType TYPE_HANDLER_TYPE
   18.37 +            = MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class);
   18.38 +    }
   18.39 +
   18.40      /** Can a checkcast adapter validly convert the target to newType?
   18.41       *  The JVM supports all kind of reference casts, even silly ones.
   18.42       */
    19.1 --- a/src/share/classes/sun/dyn/BoundMethodHandle.java	Tue Dec 21 15:27:55 2010 -0800
    19.2 +++ b/src/share/classes/sun/dyn/BoundMethodHandle.java	Tue Dec 21 18:45:45 2010 -0800
    19.3 @@ -103,21 +103,20 @@
    19.4          super(Access.TOKEN, type);
    19.5          this.argument = argument;
    19.6          this.vmargslot = vmargslot;
    19.7 -        assert(this.getClass() == AdapterMethodHandle.class);
    19.8 +        assert(this instanceof AdapterMethodHandle);
    19.9      }
   19.10  
   19.11 -    /** Initialize the current object as a Java method handle, binding it
   19.12 +    /** Initialize the current object as a self-bound method handle, binding it
   19.13       *  as the first argument of the method handle {@code entryPoint}.
   19.14       *  The invocation type of the resulting method handle will be the
   19.15       *  same as {@code entryPoint},  except that the first argument
   19.16       *  type will be dropped.
   19.17       */
   19.18 -    protected BoundMethodHandle(MethodHandle entryPoint) {
   19.19 -        super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1));
   19.20 +    protected BoundMethodHandle(Access token, MethodHandle entryPoint) {
   19.21 +        super(token, entryPoint.type().dropParameterTypes(0, 1));
   19.22          this.argument = this; // kludge; get rid of
   19.23          this.vmargslot = this.type().parameterSlotDepth(0);
   19.24          initTarget(entryPoint, 0);
   19.25 -        assert(this instanceof JavaMethodHandle);
   19.26      }
   19.27  
   19.28      /** Make sure the given {@code argument} can be used as {@code argnum}-th
   19.29 @@ -173,6 +172,11 @@
   19.30  
   19.31      @Override
   19.32      public String toString() {
   19.33 +        return MethodHandleImpl.addTypeString(baseName(), this);
   19.34 +    }
   19.35 +
   19.36 +    /** Component of toString() before the type string. */
   19.37 +    protected String baseName() {
   19.38          MethodHandle mh = this;
   19.39          while (mh instanceof BoundMethodHandle) {
   19.40              Object info = MethodHandleNatives.getTargetInfo(mh);
   19.41 @@ -185,12 +189,16 @@
   19.42                  if (name != null)
   19.43                      return name;
   19.44                  else
   19.45 -                    return super.toString(); // <unknown>, probably
   19.46 +                    return noParens(super.toString()); // "invoke", probably
   19.47              }
   19.48              assert(mh != this);
   19.49 -            if (mh instanceof JavaMethodHandle)
   19.50 -                break;  // access JMH.toString(), not BMH.toString()
   19.51          }
   19.52 -        return mh.toString();
   19.53 +        return noParens(mh.toString());
   19.54 +    }
   19.55 +
   19.56 +    private static String noParens(String str) {
   19.57 +        int paren = str.indexOf('(');
   19.58 +        if (paren >= 0) str = str.substring(0, paren);
   19.59 +        return str;
   19.60      }
   19.61  }
    20.1 --- a/src/share/classes/sun/dyn/CallSiteImpl.java	Tue Dec 21 15:27:55 2010 -0800
    20.2 +++ b/src/share/classes/sun/dyn/CallSiteImpl.java	Tue Dec 21 18:45:45 2010 -0800
    20.3 @@ -41,31 +41,45 @@
    20.4                               Object info,
    20.5                               // Caller information:
    20.6                               MemberName callerMethod, int callerBCI) {
    20.7 -        Class<?> caller = callerMethod.getDeclaringClass();
    20.8 +        Class<?> callerClass = callerMethod.getDeclaringClass();
    20.9 +        Object caller;
   20.10 +        if (bootstrapMethod.type().parameterType(0) == Class.class)
   20.11 +            caller = callerClass;  // remove for PFD
   20.12 +        else
   20.13 +            caller = MethodHandleImpl.IMPL_LOOKUP.in(callerClass);
   20.14          if (bootstrapMethod == null) {
   20.15              // If there is no bootstrap method, throw IncompatibleClassChangeError.
   20.16              // This is a valid generic error type for resolution (JLS 12.3.3).
   20.17              throw new IncompatibleClassChangeError
   20.18 -                ("Class "+caller.getName()+" has not declared a bootstrap method for invokedynamic");
   20.19 +                ("Class "+callerClass.getName()+" has not declared a bootstrap method for invokedynamic");
   20.20          }
   20.21          CallSite site;
   20.22          try {
   20.23              Object binding;
   20.24 -            if (false)  // switch when invokeGeneric works
   20.25 -                binding = bootstrapMethod.invokeGeneric(caller, name, type);
   20.26 -            else
   20.27 -                binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type });
   20.28 +            if (info == null) {
   20.29 +                if (false)  // switch when invokeGeneric works
   20.30 +                    binding = bootstrapMethod.invokeGeneric(caller, name, type);
   20.31 +                else
   20.32 +                    binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type });
   20.33 +            } else {
   20.34 +                info = maybeReBox(info);
   20.35 +                if (false)  // switch when invokeGeneric works
   20.36 +                    binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
   20.37 +                else
   20.38 +                    binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type, info });
   20.39 +            }
   20.40              //System.out.println("BSM for "+name+type+" => "+binding);
   20.41              if (binding instanceof CallSite) {
   20.42                  site = (CallSite) binding;
   20.43 -            } else if (binding instanceof MethodHandleProvider) {
   20.44 -                MethodHandle target = ((MethodHandleProvider) binding).asMethodHandle();
   20.45 +            } else if (binding instanceof MethodHandle) {
   20.46 +                // Transitional!
   20.47 +                MethodHandle target = (MethodHandle) binding;
   20.48                  site = new ConstantCallSite(target);
   20.49              } else {
   20.50                  throw new ClassCastException("bootstrap method failed to produce a MethodHandle or CallSite");
   20.51              }
   20.52 -            PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site, name, type,
   20.53 -                                                           callerMethod, callerBCI);
   20.54 +            PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type,
   20.55 +                                                     callerMethod, callerBCI);
   20.56              assert(site.getTarget() != null);
   20.57              assert(site.getTarget().type().equals(type));
   20.58          } catch (Throwable ex) {
   20.59 @@ -79,6 +93,24 @@
   20.60          return site;
   20.61      }
   20.62  
   20.63 +    private static Object maybeReBox(Object x) {
   20.64 +        if (x instanceof Integer) {
   20.65 +            int xi = (int) x;
   20.66 +            if (xi == (byte) xi)
   20.67 +                x = xi;  // must rebox; see JLS 5.1.7
   20.68 +            return x;
   20.69 +        } else if (x instanceof Object[]) {
   20.70 +            Object[] xa = (Object[]) x;
   20.71 +            for (int i = 0; i < xa.length; i++) {
   20.72 +                if (xa[i] instanceof Integer)
   20.73 +                    xa[i] = maybeReBox(xa[i]);
   20.74 +            }
   20.75 +            return xa;
   20.76 +        } else {
   20.77 +            return x;
   20.78 +        }
   20.79 +    }
   20.80 +
   20.81      // This method is private in CallSite because it touches private fields in CallSite.
   20.82      // These private fields (vmmethod, vmindex) are specific to the JVM.
   20.83      private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
    21.1 --- a/src/share/classes/sun/dyn/FilterGeneric.java	Tue Dec 21 15:27:55 2010 -0800
    21.2 +++ b/src/share/classes/sun/dyn/FilterGeneric.java	Tue Dec 21 18:45:45 2010 -0800
    21.3 @@ -115,7 +115,7 @@
    21.4  
    21.5      static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
    21.6          FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
    21.7 -        return fgen.makeInstance(kind, pos, filter, target).asMethodHandle();
    21.8 +        return fgen.makeInstance(kind, pos, filter, target);
    21.9      }
   21.10  
   21.11      /** Return the adapter information for this target and filter type. */
   21.12 @@ -225,13 +225,13 @@
   21.13       * The invoker is kept separate from the target because it can be
   21.14       * generated once per type erasure family, and reused across adapters.
   21.15       */
   21.16 -    static abstract class Adapter extends JavaMethodHandle {
   21.17 +    static abstract class Adapter extends BoundMethodHandle {
   21.18          protected final MethodHandle filter; // transforms one or more arguments
   21.19          protected final MethodHandle target; // ultimate target
   21.20  
   21.21          @Override
   21.22          public String toString() {
   21.23 -            return target.toString();
   21.24 +            return MethodHandleImpl.addTypeString(target, this);
   21.25          }
   21.26  
   21.27          protected boolean isPrototype() { return target == null; }
   21.28 @@ -246,7 +246,7 @@
   21.29  
   21.30          protected Adapter(MethodHandle entryPoint,
   21.31                            MethodHandle filter, MethodHandle target) {
   21.32 -            super(entryPoint);
   21.33 +            super(Access.TOKEN, entryPoint);
   21.34              this.filter = filter;
   21.35              this.target = target;
   21.36          }
   21.37 @@ -303,7 +303,7 @@
   21.38          protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
   21.39          protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); }
   21.40          protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
   21.41 -                       filter.<void>invokeExact(av); return target.invokeExact(av[0]); }
   21.42 +                       filter.invokeExact(av); return target.invokeExact(av[0]); }
   21.43      }
   21.44      static class F2X extends Adapter {
   21.45          protected F2X(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
   21.46 @@ -320,7 +320,7 @@
   21.47          protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
   21.48          protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); }
   21.49          protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
   21.50 -                       filter.<void>invokeExact(av); return target.invokeExact(av[0], av[1]); }
   21.51 +                       filter.invokeExact(av); return target.invokeExact(av[0], av[1]); }
   21.52      }
   21.53      // */
   21.54  
   21.55 @@ -337,7 +337,7 @@
   21.56              return target.invokeExact(filter.invokeExact()); }
   21.57          static final Object[] NO_ARGS = { };
   21.58          protected Object invoke_Y0() throws Throwable {
   21.59 -            filter.<void>invokeExact(NO_ARGS); // make the flyby
   21.60 +            filter.invokeExact(NO_ARGS); // make the flyby
   21.61              return target.invokeExact(); }
   21.62      }
   21.63  
   21.64 @@ -375,7 +375,7 @@
   21.65          "            return target.invokeExact(@av@, filter.invokeExact()); }",
   21.66          "        protected Object invoke_Y0(@Tvav@) throws Throwable {",
   21.67          "            Object[] av = { @av@ };",
   21.68 -        "            filter.<void>invokeExact(av); // make the flyby",
   21.69 +        "            filter.invokeExact(av); // make the flyby",
   21.70          "            return target.invokeExact(@av[i]@); }",
   21.71          "    }",
   21.72      } };
   21.73 @@ -518,7 +518,7 @@
   21.74              return target.invokeExact(a0, filter.invokeExact()); }
   21.75          protected Object invoke_Y0(Object a0) throws Throwable {
   21.76              Object[] av = { a0 };
   21.77 -            filter.<void>invokeExact(av); // make the flyby
   21.78 +            filter.invokeExact(av); // make the flyby
   21.79              return target.invokeExact(av[0]); }
   21.80      }
   21.81      static class F2 extends Adapter {
   21.82 @@ -548,7 +548,7 @@
   21.83              return target.invokeExact(a0, a1, filter.invokeExact()); }
   21.84          protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
   21.85              Object[] av = { a0, a1 };
   21.86 -            filter.<void>invokeExact(av); // make the flyby
   21.87 +            filter.invokeExact(av); // make the flyby
   21.88              return target.invokeExact(av[0], av[1]); }
   21.89      }
   21.90      static class F3 extends Adapter {
   21.91 @@ -585,7 +585,7 @@
   21.92              return target.invokeExact(a0, a1, a2, filter.invokeExact()); }
   21.93          protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
   21.94              Object[] av = { a0, a1, a2 };
   21.95 -            filter.<void>invokeExact(av); // make the flyby
   21.96 +            filter.invokeExact(av); // make the flyby
   21.97              return target.invokeExact(av[0], av[1], av[2]); }
   21.98      }
   21.99      static class F4 extends Adapter {
  21.100 @@ -629,7 +629,7 @@
  21.101              return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); }
  21.102          protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
  21.103              Object[] av = { a0, a1, a2, a3 };
  21.104 -            filter.<void>invokeExact(av); // make the flyby
  21.105 +            filter.invokeExact(av); // make the flyby
  21.106              return target.invokeExact(av[0], av[1], av[2], av[3]); }
  21.107      }
  21.108      static class F5 extends Adapter {
  21.109 @@ -698,7 +698,7 @@
  21.110          protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
  21.111                                     Object a4) throws Throwable {
  21.112              Object[] av = { a0, a1, a2, a3, a4 };
  21.113 -            filter.<void>invokeExact(av); // make the flyby
  21.114 +            filter.invokeExact(av); // make the flyby
  21.115              return target.invokeExact(av[0], av[1], av[2], av[3], av[4]); }
  21.116      }
  21.117      static class F6 extends Adapter {
  21.118 @@ -777,7 +777,7 @@
  21.119          protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
  21.120                                     Object a4, Object a5) throws Throwable {
  21.121              Object[] av = { a0, a1, a2, a3, a4, a5 };
  21.122 -            filter.<void>invokeExact(av); // make the flyby
  21.123 +            filter.invokeExact(av); // make the flyby
  21.124              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5]); }
  21.125      }
  21.126      static class F7 extends Adapter {
  21.127 @@ -866,7 +866,7 @@
  21.128          protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
  21.129                                     Object a4, Object a5, Object a6) throws Throwable {
  21.130              Object[] av = { a0, a1, a2, a3, a4, a5, a6 };
  21.131 -            filter.<void>invokeExact(av); // make the flyby
  21.132 +            filter.invokeExact(av); // make the flyby
  21.133              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); }
  21.134      }
  21.135      static class F8 extends Adapter {
  21.136 @@ -965,7 +965,7 @@
  21.137          protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
  21.138                                     Object a4, Object a5, Object a6, Object a7) throws Throwable {
  21.139              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 };
  21.140 -            filter.<void>invokeExact(av); // make the flyby
  21.141 +            filter.invokeExact(av); // make the flyby
  21.142              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); }
  21.143      }
  21.144      static class F9 extends Adapter {
  21.145 @@ -1104,7 +1104,7 @@
  21.146                                     Object a4, Object a5, Object a6, Object a7,
  21.147                                     Object a8) throws Throwable {
  21.148              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 };
  21.149 -            filter.<void>invokeExact(av); // make the flyby
  21.150 +            filter.invokeExact(av); // make the flyby
  21.151              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); }
  21.152      }
  21.153      static class F10 extends Adapter {
  21.154 @@ -1256,7 +1256,7 @@
  21.155                                     Object a4, Object a5, Object a6, Object a7,
  21.156                                     Object a8, Object a9) throws Throwable {
  21.157              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 };
  21.158 -            filter.<void>invokeExact(av); // make the flyby
  21.159 +            filter.invokeExact(av); // make the flyby
  21.160              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); }
  21.161      }
  21.162      static class F11 extends Adapter {
  21.163 @@ -1442,7 +1442,7 @@
  21.164                                     Object a4, Object a5, Object a6, Object a7,
  21.165                                     Object a8, Object a9, Object a10) throws Throwable {
  21.166              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 };
  21.167 -            filter.<void>invokeExact(av); // make the flyby
  21.168 +            filter.invokeExact(av); // make the flyby
  21.169              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); }
  21.170      }
  21.171      static class F12 extends Adapter {
  21.172 @@ -1644,7 +1644,7 @@
  21.173                                     Object a4, Object a5, Object a6, Object a7,
  21.174                                     Object a8, Object a9, Object a10, Object a11) throws Throwable {
  21.175              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 };
  21.176 -            filter.<void>invokeExact(av); // make the flyby
  21.177 +            filter.invokeExact(av); // make the flyby
  21.178              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); }
  21.179      }
  21.180      static class F13 extends Adapter {
  21.181 @@ -1904,7 +1904,7 @@
  21.182                                     Object a8, Object a9, Object a10, Object a11,
  21.183                                     Object a12) throws Throwable {
  21.184              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 };
  21.185 -            filter.<void>invokeExact(av); // make the flyby
  21.186 +            filter.invokeExact(av); // make the flyby
  21.187              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); }
  21.188      }
  21.189      static class F14 extends Adapter {
  21.190 @@ -2183,7 +2183,7 @@
  21.191                                     Object a8, Object a9, Object a10, Object a11,
  21.192                                     Object a12, Object a13) throws Throwable {
  21.193              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 };
  21.194 -            filter.<void>invokeExact(av); // make the flyby
  21.195 +            filter.invokeExact(av); // make the flyby
  21.196              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); }
  21.197      }
  21.198      static class F15 extends Adapter {
  21.199 @@ -2481,7 +2481,7 @@
  21.200                                     Object a8, Object a9, Object a10, Object a11,
  21.201                                     Object a12, Object a13, Object a14) throws Throwable {
  21.202              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
  21.203 -            filter.<void>invokeExact(av); // make the flyby
  21.204 +            filter.invokeExact(av); // make the flyby
  21.205              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); }
  21.206      }
  21.207      static class F16 extends Adapter {
  21.208 @@ -2798,7 +2798,7 @@
  21.209                                     Object a8, Object a9, Object a10, Object a11,
  21.210                                     Object a12, Object a13, Object a14, Object a15) throws Throwable {
  21.211              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 };
  21.212 -            filter.<void>invokeExact(av); // make the flyby
  21.213 +            filter.invokeExact(av); // make the flyby
  21.214              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); }
  21.215      }
  21.216      static class F17 extends Adapter {
  21.217 @@ -3188,7 +3188,7 @@
  21.218                                     Object a12, Object a13, Object a14, Object a15,
  21.219                                     Object a16) throws Throwable {
  21.220              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 };
  21.221 -            filter.<void>invokeExact(av); // make the flyby
  21.222 +            filter.invokeExact(av); // make the flyby
  21.223              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); }
  21.224      }
  21.225      static class F18 extends Adapter {
  21.226 @@ -3600,7 +3600,7 @@
  21.227                                     Object a12, Object a13, Object a14, Object a15,
  21.228                                     Object a16, Object a17) throws Throwable {
  21.229              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 };
  21.230 -            filter.<void>invokeExact(av); // make the flyby
  21.231 +            filter.invokeExact(av); // make the flyby
  21.232              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); }
  21.233      }
  21.234      static class F19 extends Adapter {
  21.235 @@ -4034,7 +4034,7 @@
  21.236                                     Object a12, Object a13, Object a14, Object a15,
  21.237                                     Object a16, Object a17, Object a18) throws Throwable {
  21.238              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 };
  21.239 -            filter.<void>invokeExact(av); // make the flyby
  21.240 +            filter.invokeExact(av); // make the flyby
  21.241              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); }
  21.242      }
  21.243      static class F20 extends Adapter {
  21.244 @@ -4490,7 +4490,7 @@
  21.245                                     Object a12, Object a13, Object a14, Object a15,
  21.246                                     Object a16, Object a17, Object a18, Object a19) throws Throwable {
  21.247              Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 };
  21.248 -            filter.<void>invokeExact(av); // make the flyby
  21.249 +            filter.invokeExact(av); // make the flyby
  21.250              return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); }
  21.251      }
  21.252  }
    22.1 --- a/src/share/classes/sun/dyn/FilterOneArgument.java	Tue Dec 21 15:27:55 2010 -0800
    22.2 +++ b/src/share/classes/sun/dyn/FilterOneArgument.java	Tue Dec 21 18:45:45 2010 -0800
    22.3 @@ -36,7 +36,7 @@
    22.4   * final method type is the responsibility of a JVM-level adapter.
    22.5   * @author jrose
    22.6   */
    22.7 -public class FilterOneArgument extends JavaMethodHandle {
    22.8 +public class FilterOneArgument extends BoundMethodHandle {
    22.9      protected final MethodHandle filter;  // Object -> Object
   22.10      protected final MethodHandle target;  // Object -> Object
   22.11  
   22.12 @@ -62,7 +62,7 @@
   22.13      }
   22.14  
   22.15      protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
   22.16 -        super(INVOKE);
   22.17 +        super(Access.TOKEN, INVOKE);
   22.18          this.filter = filter;
   22.19          this.target = target;
   22.20      }
    23.1 --- a/src/share/classes/sun/dyn/FromGeneric.java	Tue Dec 21 15:27:55 2010 -0800
    23.2 +++ b/src/share/classes/sun/dyn/FromGeneric.java	Tue Dec 21 18:45:45 2010 -0800
    23.3 @@ -241,7 +241,7 @@
    23.4       * The invoker is kept separate from the target because it can be
    23.5       * generated once per type erasure family, and reused across adapters.
    23.6       */
    23.7 -    static abstract class Adapter extends JavaMethodHandle {
    23.8 +    static abstract class Adapter extends BoundMethodHandle {
    23.9          /*
   23.10           * class X<<R,int N>> extends Adapter {
   23.11           *   (MH, Object**N)=>raw(R) invoker;
   23.12 @@ -256,7 +256,7 @@
   23.13  
   23.14          @Override
   23.15          public String toString() {
   23.16 -            return target.toString();
   23.17 +            return MethodHandleImpl.addTypeString(target, this);
   23.18          }
   23.19  
   23.20          protected boolean isPrototype() { return target == null; }
   23.21 @@ -271,7 +271,7 @@
   23.22  
   23.23          protected Adapter(MethodHandle entryPoint,
   23.24                            MethodHandle invoker, MethodHandle convert, MethodHandle target) {
   23.25 -            super(entryPoint);
   23.26 +            super(Access.TOKEN, entryPoint);
   23.27              this.invoker = invoker;
   23.28              this.convert = convert;
   23.29              this.target  = target;
   23.30 @@ -283,11 +283,11 @@
   23.31          // { return new ThisType(entryPoint, convert, target); }
   23.32  
   23.33          /// Conversions on the value returned from the target.
   23.34 -        protected Object convert_L(Object result) throws Throwable { return convert.<Object>invokeExact(result); }
   23.35 -        protected Object convert_I(int    result) throws Throwable { return convert.<Object>invokeExact(result); }
   23.36 -        protected Object convert_J(long   result) throws Throwable { return convert.<Object>invokeExact(result); }
   23.37 -        protected Object convert_F(float  result) throws Throwable { return convert.<Object>invokeExact(result); }
   23.38 -        protected Object convert_D(double result) throws Throwable { return convert.<Object>invokeExact(result); }
   23.39 +        protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
   23.40 +        protected Object convert_I(int    result) throws Throwable { return convert.invokeExact(result); }
   23.41 +        protected Object convert_J(long   result) throws Throwable { return convert.invokeExact(result); }
   23.42 +        protected Object convert_F(float  result) throws Throwable { return convert.invokeExact(result); }
   23.43 +        protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
   23.44  
   23.45          static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
   23.46          static {
   23.47 @@ -316,11 +316,11 @@
   23.48                          { super(e, i, c, t); }
   23.49          protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
   23.50                          { return new xA2(e, i, c, t); }
   23.51 -        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1)); }
   23.52 -        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1)); }
   23.53 -        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1)); }
   23.54 -        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1)); }
   23.55 -        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1)); }
   23.56 +        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
   23.57 +        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
   23.58 +        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
   23.59 +        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
   23.60 +        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
   23.61      }
   23.62      // */
   23.63  
   23.64 @@ -329,7 +329,8 @@
   23.65  //{{{
   23.66  import java.util.*;
   23.67  class genclasses {
   23.68 -    static String[] TYPES = { "Object", "int   ", "long  ", "float ", "double" };
   23.69 +    static String[] TYPES = { "Object",    "int   ",    "long  ",    "float ",    "double" };
   23.70 +    static String[] WRAPS = { "         ", "(Integer)", "(Long)   ", "(Float)  ", "(Double) " };
   23.71      static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
   23.72      static String[][] TEMPLATES = { {
   23.73          "@for@ arity=0..10  rcat<=4 nrefs<=99 nints=0   nlongs=0",
   23.74 @@ -341,13 +342,13 @@
   23.75          "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
   23.76          "                        { return new @cat@(e, i, c, t); }",
   23.77          "        //@each-R@",
   23.78 -        "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@(invoker.<@R@>invokeExact(target@av@)); }",
   23.79 +        "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
   23.80          "        //@end-R@",
   23.81          "    }",
   23.82      } };
   23.83      static final String NEWLINE_INDENT = "\n                ";
   23.84      enum VAR {
   23.85 -        cat, catN, R, Rc, av, Tvav, Ovav;
   23.86 +        cat, catN, R, Rc, W, av, Tvav, Ovav;
   23.87          public final String pattern = "@"+toString().replace('_','.')+"@";
   23.88          public String binding;
   23.89          static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
   23.90 @@ -357,6 +358,7 @@
   23.91              VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
   23.92              VAR.R.binding = TYPES[rcat];
   23.93              VAR.Rc.binding = TCHARS[rcat];
   23.94 +            VAR.W.binding = WRAPS[rcat];
   23.95              String[] Tv = new String[nargs];
   23.96              String[] av = new String[nargs];
   23.97              String[] Tvav = new String[nargs];
   23.98 @@ -497,11 +499,11 @@
   23.99                          { super(e, i, c, t); }
  23.100          protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.101                          { return new A0(e, i, c, t); }
  23.102 -        protected Object invoke_L0() throws Throwable { return convert_L(invoker.<Object>invokeExact(target)); }
  23.103 -        protected Object invoke_I0() throws Throwable { return convert_I(invoker.<int   >invokeExact(target)); }
  23.104 -        protected Object invoke_J0() throws Throwable { return convert_J(invoker.<long  >invokeExact(target)); }
  23.105 -        protected Object invoke_F0() throws Throwable { return convert_F(invoker.<float >invokeExact(target)); }
  23.106 -        protected Object invoke_D0() throws Throwable { return convert_D(invoker.<double>invokeExact(target)); }
  23.107 +        protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
  23.108 +        protected Object invoke_I0() throws Throwable { return convert_I((int)   invoker.invokeExact(target)); }
  23.109 +        protected Object invoke_J0() throws Throwable { return convert_J((long)  invoker.invokeExact(target)); }
  23.110 +        protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
  23.111 +        protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
  23.112      }
  23.113      static class A1 extends Adapter {
  23.114          protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.115 @@ -509,11 +511,11 @@
  23.116                          { super(e, i, c, t); }
  23.117          protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.118                          { return new A1(e, i, c, t); }
  23.119 -        protected Object invoke_L1(Object a0) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0)); }
  23.120 -        protected Object invoke_I1(Object a0) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0)); }
  23.121 -        protected Object invoke_J1(Object a0) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0)); }
  23.122 -        protected Object invoke_F1(Object a0) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0)); }
  23.123 -        protected Object invoke_D1(Object a0) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0)); }
  23.124 +        protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
  23.125 +        protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0)); }
  23.126 +        protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0)); }
  23.127 +        protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
  23.128 +        protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); }
  23.129      }
  23.130      static class A2 extends Adapter {
  23.131          protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.132 @@ -521,11 +523,11 @@
  23.133                          { super(e, i, c, t); }
  23.134          protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.135                          { return new A2(e, i, c, t); }
  23.136 -        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1)); }
  23.137 -        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1)); }
  23.138 -        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1)); }
  23.139 -        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1)); }
  23.140 -        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1)); }
  23.141 +        protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
  23.142 +        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
  23.143 +        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
  23.144 +        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
  23.145 +        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
  23.146      }
  23.147      static class A3 extends Adapter {
  23.148          protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.149 @@ -533,11 +535,11 @@
  23.150                          { super(e, i, c, t); }
  23.151          protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.152                          { return new A3(e, i, c, t); }
  23.153 -        protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2)); }
  23.154 -        protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2)); }
  23.155 -        protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2)); }
  23.156 -        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2)); }
  23.157 -        protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2)); }
  23.158 +        protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
  23.159 +        protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2)); }
  23.160 +        protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2)); }
  23.161 +        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
  23.162 +        protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
  23.163      }
  23.164      static class A4 extends Adapter {
  23.165          protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.166 @@ -545,11 +547,11 @@
  23.167                          { super(e, i, c, t); }
  23.168          protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.169                          { return new A4(e, i, c, t); }
  23.170 -        protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3)); }
  23.171 -        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3)); }
  23.172 -        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3)); }
  23.173 -        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3)); }
  23.174 -        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3)); }
  23.175 +        protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
  23.176 +        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3)); }
  23.177 +        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3)); }
  23.178 +        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
  23.179 +        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); }
  23.180      }
  23.181      static class A5 extends Adapter {
  23.182          protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.183 @@ -557,11 +559,11 @@
  23.184                          { super(e, i, c, t); }
  23.185          protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.186                          { return new A5(e, i, c, t); }
  23.187 -        protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4)); }
  23.188 -        protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4)); }
  23.189 -        protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4)); }
  23.190 -        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4)); }
  23.191 -        protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4)); }
  23.192 +        protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
  23.193 +        protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
  23.194 +        protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
  23.195 +        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
  23.196 +        protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
  23.197      }
  23.198      static class A6 extends Adapter {
  23.199          protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.200 @@ -569,11 +571,11 @@
  23.201                          { super(e, i, c, t); }
  23.202          protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.203                          { return new A6(e, i, c, t); }
  23.204 -        protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.205 -        protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.206 -        protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.207 -        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.208 -        protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.209 +        protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.210 +        protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.211 +        protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.212 +        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.213 +        protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
  23.214      }
  23.215      static class A7 extends Adapter {
  23.216          protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.217 @@ -581,11 +583,11 @@
  23.218                          { super(e, i, c, t); }
  23.219          protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.220                          { return new A7(e, i, c, t); }
  23.221 -        protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.222 -        protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.223 -        protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.224 -        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.225 -        protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.226 +        protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.227 +        protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.228 +        protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.229 +        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.230 +        protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
  23.231      }
  23.232      static class A8 extends Adapter {
  23.233          protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.234 @@ -593,11 +595,11 @@
  23.235                          { super(e, i, c, t); }
  23.236          protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.237                          { return new A8(e, i, c, t); }
  23.238 -        protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.239 -        protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.240 -        protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.241 -        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.242 -        protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.243 +        protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.244 +        protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.245 +        protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.246 +        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.247 +        protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  23.248      }
  23.249      static class A9 extends Adapter {
  23.250          protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.251 @@ -605,11 +607,11 @@
  23.252                          { super(e, i, c, t); }
  23.253          protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.254                          { return new A9(e, i, c, t); }
  23.255 -        protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.256 -        protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.257 -        protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.258 -        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.259 -        protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.260 +        protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.261 +        protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.262 +        protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.263 +        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.264 +        protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  23.265      }
  23.266      static class A10 extends Adapter {
  23.267          protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  23.268 @@ -617,10 +619,10 @@
  23.269                          { super(e, i, c, t); }
  23.270          protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  23.271                          { return new A10(e, i, c, t); }
  23.272 -        protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L(invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.273 -        protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I(invoker.<int   >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.274 -        protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J(invoker.<long  >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.275 -        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F(invoker.<float >invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.276 -        protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D(invoker.<double>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.277 +        protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.278 +        protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.279 +        protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.280 +        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.281 +        protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  23.282      }
  23.283  }
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/share/classes/sun/dyn/InvokeGeneric.java	Tue Dec 21 18:45:45 2010 -0800
    24.3 @@ -0,0 +1,160 @@
    24.4 +/*
    24.5 + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + *
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.  Oracle designates this
   24.11 + * particular file as subject to the "Classpath" exception as provided
   24.12 + * by Oracle in the LICENSE file that accompanied this code.
   24.13 + *
   24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 + * version 2 for more details (a copy is included in the LICENSE file that
   24.18 + * accompanied this code).
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License version
   24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 + *
   24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.25 + * or visit www.oracle.com if you need additional information or have any
   24.26 + * questions.
   24.27 + */
   24.28 +
   24.29 +package sun.dyn;
   24.30 +
   24.31 +import java.dyn.*;
   24.32 +import java.lang.reflect.*;
   24.33 +import sun.dyn.util.*;
   24.34 +
   24.35 +/**
   24.36 + * Adapters which manage MethodHanndle.invokeGeneric calls.
   24.37 + * The JVM calls one of these when the exact type match fails.
   24.38 + * @author jrose
   24.39 + */
   24.40 +class InvokeGeneric {
   24.41 +    // erased type for the call, which originates from an invokeGeneric site
   24.42 +    private final MethodType erasedCallerType;
   24.43 +    // an invoker of type (MT, MH; A...) -> R
   24.44 +    private final MethodHandle initialInvoker;
   24.45 +
   24.46 +    /** Compute and cache information for this adapter, so that it can
   24.47 +     *  call out to targets of the erasure-family of the given erased type.
   24.48 +     */
   24.49 +    private InvokeGeneric(MethodType erasedCallerType) throws NoAccessException {
   24.50 +        this.erasedCallerType = erasedCallerType;
   24.51 +        this.initialInvoker = makeInitialInvoker();
   24.52 +        assert initialInvoker.type().equals(erasedCallerType
   24.53 +                                            .insertParameterTypes(0, MethodType.class, MethodHandle.class))
   24.54 +            : initialInvoker.type();
   24.55 +    }
   24.56 +
   24.57 +    private static MethodHandles.Lookup lookup() {
   24.58 +        return MethodHandleImpl.IMPL_LOOKUP;
   24.59 +    }
   24.60 +
   24.61 +    /** Return the adapter information for this type's erasure. */
   24.62 +    static MethodHandle genericInvokerOf(MethodType type) {
   24.63 +        MethodTypeImpl form = MethodTypeImpl.of(type);
   24.64 +        MethodHandle genericInvoker = form.genericInvoker;
   24.65 +        if (genericInvoker == null) {
   24.66 +            try {
   24.67 +                InvokeGeneric gen = new InvokeGeneric(form.erasedType());
   24.68 +                form.genericInvoker = genericInvoker = gen.initialInvoker;
   24.69 +            } catch (NoAccessException ex) {
   24.70 +                throw new RuntimeException(ex);
   24.71 +            }
   24.72 +        }
   24.73 +        return genericInvoker;
   24.74 +    }
   24.75 +
   24.76 +    private MethodHandle makeInitialInvoker() throws NoAccessException {
   24.77 +        // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)}
   24.78 +        MethodHandle postDispatch = makePostDispatchInvoker();
   24.79 +        MethodHandle invoker;
   24.80 +        if (returnConversionPossible()) {
   24.81 +            invoker = MethodHandles.foldArguments(postDispatch,
   24.82 +                                                  dispatcher("dispatchWithConversion"));
   24.83 +        } else {
   24.84 +            invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch"));
   24.85 +        }
   24.86 +        return invoker;
   24.87 +    }
   24.88 +
   24.89 +    private static final Class<?>[] EXTRA_ARGS = { MethodType.class, MethodHandle.class };
   24.90 +    private MethodHandle makePostDispatchInvoker() {
   24.91 +        // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
   24.92 +        MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
   24.93 +        return MethodHandles.exactInvoker(invokerType);
   24.94 +    }
   24.95 +    private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
   24.96 +        assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
   24.97 +        return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS);
   24.98 +    }
   24.99 +
  24.100 +    private MethodHandle dispatcher(String dispatchName) throws NoAccessException {
  24.101 +        return lookup().bind(this, dispatchName,
  24.102 +                             MethodType.methodType(MethodHandle.class,
  24.103 +                                                   MethodType.class, MethodHandle.class));
  24.104 +    }
  24.105 +
  24.106 +    static final boolean USE_AS_TYPE_PATH = true;
  24.107 +
  24.108 +    /** Return a method handle to invoke on the callerType, target, and remaining arguments.
  24.109 +     *  The method handle must finish the call.
  24.110 +     *  This is the first look at the caller type and target.
  24.111 +     */
  24.112 +    private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
  24.113 +        MethodType targetType = target.type();
  24.114 +        if (USE_AS_TYPE_PATH || target instanceof AdapterMethodHandle.WithTypeHandler) {
  24.115 +            MethodHandle newTarget = target.asType(callerType);
  24.116 +            targetType = callerType;
  24.117 +            Invokers invokers = MethodTypeImpl.invokers(Access.TOKEN, targetType);
  24.118 +            MethodHandle invoker = invokers.erasedInvokerWithDrops;
  24.119 +            if (invoker == null) {
  24.120 +                invokers.erasedInvokerWithDrops = invoker =
  24.121 +                    dropDispatchArguments(invokers.erasedInvoker());
  24.122 +            }
  24.123 +            return invoker.bindTo(newTarget);
  24.124 +        }
  24.125 +        throw new RuntimeException("NYI");
  24.126 +    }
  24.127 +
  24.128 +    private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) {
  24.129 +        MethodHandle finisher = dispatch(callerType, target);
  24.130 +        if (returnConversionNeeded(callerType, target))
  24.131 +            finisher = addReturnConversion(finisher, callerType.returnType());  //FIXME: slow
  24.132 +        return finisher;
  24.133 +    }
  24.134 +
  24.135 +    private boolean returnConversionPossible() {
  24.136 +        Class<?> needType = erasedCallerType.returnType();
  24.137 +        return !needType.isPrimitive();
  24.138 +    }
  24.139 +    private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
  24.140 +        Class<?> needType = callerType.returnType();
  24.141 +        if (needType == erasedCallerType.returnType())
  24.142 +            return false;  // no conversions possible, since must be primitive or Object
  24.143 +        Class<?> haveType = target.type().returnType();
  24.144 +        if (VerifyType.isNullConversion(haveType, needType))
  24.145 +            return false;
  24.146 +        return true;
  24.147 +    }
  24.148 +    private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
  24.149 +        if (true) throw new RuntimeException("NYI");
  24.150 +        // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
  24.151 +        MethodType targetType = target.type();
  24.152 +        MethodHandle caster = ValueConversions.identity(type);
  24.153 +        caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
  24.154 +        // Drop irrelevant arguments, because we only care about the return value:
  24.155 +        caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
  24.156 +        MethodHandle result = MethodHandles.foldArguments(caster, target);
  24.157 +        return result.asType(target.type());
  24.158 +    }
  24.159 +
  24.160 +    public String toString() {
  24.161 +        return "InvokeGeneric"+erasedCallerType;
  24.162 +    }
  24.163 +}
    25.1 --- a/src/share/classes/sun/dyn/Invokers.java	Tue Dec 21 15:27:55 2010 -0800
    25.2 +++ b/src/share/classes/sun/dyn/Invokers.java	Tue Dec 21 18:45:45 2010 -0800
    25.3 @@ -26,6 +26,7 @@
    25.4  package sun.dyn;
    25.5  
    25.6  import java.dyn.*;
    25.7 +import sun.dyn.empty.Empty;
    25.8  
    25.9  /**
   25.10   * Construction and caching of often-used invokers.
   25.11 @@ -38,12 +39,19 @@
   25.12      // exact invoker for the outgoing call
   25.13      private /*lazy*/ MethodHandle exactInvoker;
   25.14  
   25.15 +    // erased (partially untyped but with primitives) invoker for the outgoing call
   25.16 +    private /*lazy*/ MethodHandle erasedInvoker;
   25.17 +    /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
   25.18 +
   25.19      // generic (untyped) invoker for the outgoing call
   25.20      private /*lazy*/ MethodHandle genericInvoker;
   25.21  
   25.22      // generic (untyped) invoker for the outgoing call; accepts a single Object[]
   25.23      private final /*lazy*/ MethodHandle[] varargsInvokers;
   25.24  
   25.25 +    // invoker for an unbound callsite
   25.26 +    private /*lazy*/ MethodHandle uninitializedCallSite;
   25.27 +
   25.28      /** Compute and cache information common to all collecting adapters
   25.29       *  that implement members of the erasure-family of the given erased type.
   25.30       */
   25.31 @@ -80,6 +88,19 @@
   25.32          return invoker;
   25.33      }
   25.34  
   25.35 +    public MethodHandle erasedInvoker() {
   25.36 +        MethodHandle invoker1 = exactInvoker();
   25.37 +        MethodHandle invoker = erasedInvoker;
   25.38 +        if (invoker != null)  return invoker;
   25.39 +        MethodType erasedType = targetType.erase();
   25.40 +        if (erasedType == targetType.generic())
   25.41 +            invoker = genericInvoker();
   25.42 +        else
   25.43 +            invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
   25.44 +        erasedInvoker = invoker;
   25.45 +        return invoker;
   25.46 +    }
   25.47 +
   25.48      public MethodHandle varargsInvoker(int objectArgCount) {
   25.49          MethodHandle vaInvoker = varargsInvokers[objectArgCount];
   25.50          if (vaInvoker != null)  return vaInvoker;
   25.51 @@ -90,6 +111,35 @@
   25.52          return vaInvoker;
   25.53      }
   25.54  
   25.55 +    private static MethodHandle THROW_UCS = null;
   25.56 +
   25.57 +    public MethodHandle uninitializedCallSite() {
   25.58 +        MethodHandle invoker = uninitializedCallSite;
   25.59 +        if (invoker != null)  return invoker;
   25.60 +        if (targetType.parameterCount() > 0) {
   25.61 +            MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
   25.62 +            Invokers invokers0 = MethodTypeImpl.invokers(Access.TOKEN, type0);
   25.63 +            invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
   25.64 +                                                  0, targetType.parameterList());
   25.65 +            assert(invoker.type().equals(targetType));
   25.66 +            uninitializedCallSite = invoker;
   25.67 +            return invoker;
   25.68 +        }
   25.69 +        if (THROW_UCS == null) {
   25.70 +            try {
   25.71 +                THROW_UCS = MethodHandleImpl.IMPL_LOOKUP
   25.72 +                    .findStatic(CallSite.class, "uninitializedCallSite",
   25.73 +                                MethodType.methodType(Empty.class));
   25.74 +            } catch (NoAccessException ex) {
   25.75 +                throw new RuntimeException(ex);
   25.76 +            }
   25.77 +        }
   25.78 +        invoker = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, targetType, THROW_UCS);
   25.79 +        assert(invoker.type().equals(targetType));
   25.80 +        uninitializedCallSite = invoker;
   25.81 +        return invoker;
   25.82 +    }
   25.83 +
   25.84      public String toString() {
   25.85          return "Invokers"+targetType;
   25.86      }
    26.1 --- a/src/share/classes/sun/dyn/JavaMethodHandle.java	Tue Dec 21 15:27:55 2010 -0800
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,172 +0,0 @@
    26.4 -/*
    26.5 - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. 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.  Oracle designates this
   26.11 - * particular file as subject to the "Classpath" exception as provided
   26.12 - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.25 - * or visit www.oracle.com if you need additional information or have any
   26.26 - * questions.
   26.27 - */
   26.28 -
   26.29 -package sun.dyn;
   26.30 -
   26.31 -import java.dyn.*;
   26.32 -import sun.dyn.Access;
   26.33 -
   26.34 -/**
   26.35 - * A Java method handle is a deprecated proposal for extending
   26.36 - * the basic method handle type with additional
   26.37 - * programmer defined methods and fields.
   26.38 - * Its behavior as a method handle is determined at instance creation time,
   26.39 - * by providing the new instance with an "entry point" method handle
   26.40 - * to handle calls.  This entry point must accept a leading argument
   26.41 - * whose type is the Java method handle itself or a supertype, and the
   26.42 - * entry point is always called with the Java method handle itself as
   26.43 - * the first argument.  This is similar to ordinary virtual methods, which also
   26.44 - * accept the receiver object {@code this} as an implicit leading argument.
   26.45 - * The {@code MethodType} of the Java method handle is the same as that
   26.46 - * of the entry point method handle, with the leading parameter type
   26.47 - * omitted.
   26.48 - * <p>
   26.49 - * Here is an example of usage, creating a hybrid object/functional datum:
   26.50 - * <p><blockquote><pre>
   26.51 - * class Greeter extends JavaMethodHandle {
   26.52 - *     private String greeting = "hello";
   26.53 - *     public void setGreeting(String s) { greeting = s; }
   26.54 - *     public void run() { System.out.println(greeting+", "+greetee); }
   26.55 - *     private final String greetee;
   26.56 - *     Greeter(String greetee) {
   26.57 - *         super(RUN); // alternatively, super("run")
   26.58 - *         this.greetee = greetee;
   26.59 - *     }
   26.60 - *     // the entry point function is computed once:
   26.61 - *     private static final MethodHandle RUN
   26.62 - *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
   26.63 - *               MethodType.make(void.class));
   26.64 - * }
   26.65 - * // class Main { public static void main(String... av) { ...
   26.66 - * Greeter greeter = new Greeter("world");
   26.67 - * greeter.run();  // prints "hello, world"
   26.68 - * // Statically typed method handle invocation (most direct):
   26.69 - * MethodHandle mh = greeter;
   26.70 - * mh.&lt;void&gt;invokeExact();  // also prints "hello, world"
   26.71 - * // Dynamically typed method handle invocation:
   26.72 - * MethodHandles.invokeExact(greeter);  // also prints "hello, world"
   26.73 - * greeter.setGreeting("howdy");
   26.74 - * mh.invokeExact();  // prints "howdy, world" (object-like mutable behavior)
   26.75 - * </pre></blockquote>
   26.76 - * <p>
   26.77 - * In the example of {@code Greeter}, the method {@code run} provides the entry point.
   26.78 - * The entry point need not be a constant value; it may be independently
   26.79 - * computed in each call to the constructor.  The entry point does not
   26.80 - * even need to be a method on the {@code Greeter} class, though
   26.81 - * that is the typical case.
   26.82 - * <p>
   26.83 - * The entry point may also be provided symbolically, in which case the the
   26.84 - * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
   26.85 - * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
   26.86 - * inner class:
   26.87 - * <p><blockquote><pre>
   26.88 - * // We can also do this with symbolic names and/or inner classes:
   26.89 - * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
   26.90 - *     void yow() { System.out.println("yow, world"); }
   26.91 - * });
   26.92 - * </pre></blockquote>
   26.93 - * <p>
   26.94 - * Here is similar lower-level code which works in terms of a bound method handle.
   26.95 - * <p><blockquote><pre>
   26.96 - *     class Greeter {
   26.97 - *         public void run() { System.out.println("hello, "+greetee); }
   26.98 - *         private final String greetee;
   26.99 - *         Greeter(String greetee) { this.greetee = greetee; }
  26.100 - *         // the entry point function is computed once:
  26.101 - *         private static final MethodHandle RUN
  26.102 - *             = MethodHandles.findVirtual(Greeter.class, "run",
  26.103 - *                   MethodType.make(void.class));
  26.104 - *     }
  26.105 - *     // class Main { public static void main(String... av) { ...
  26.106 - *     Greeter greeter = new Greeter("world");
  26.107 - *     greeter.run();  // prints "hello, world"
  26.108 - *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
  26.109 - *     mh.invokeExact();  // also prints "hello, world"
  26.110 - * </pre></blockquote>
  26.111 - * Note that the method handle must be separately created as a view on the base object.
  26.112 - * This increases footprint, complexity, and dynamic indirections.
  26.113 - * <p>
  26.114 - * Here is a pure functional value expressed most concisely as an anonymous inner class:
  26.115 - * <p><blockquote><pre>
  26.116 - *     // class Main { public static void main(String... av) { ...
  26.117 - *     final String greetee = "world";
  26.118 - *     MethodHandle greeter = new JavaMethodHandle("run") {
  26.119 - *         private void run() { System.out.println("hello, "+greetee); }
  26.120 - *     }
  26.121 - *     greeter.invokeExact();  // prints "hello, world"
  26.122 - * </pre></blockquote>
  26.123 - * <p>
  26.124 - * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
  26.125 - * and instantiated as an anonymous class.  The data structure is a handle to 1-D array,
  26.126 - * with a specialized index type (long).  It is created by inner class, and uses
  26.127 - * signature-polymorphic APIs throughout.
  26.128 - * <p><blockquote><pre>
  26.129 - *     abstract class AssignableMethodHandle extends JavaMethodHandle {
  26.130 - *       private final MethodHandle setter;
  26.131 - *       public MethodHandle setter() { return setter; }
  26.132 - *       public AssignableMethodHandle(String get, String set) {
  26.133 - *         super(get);
  26.134 - *         MethodType getType = this.type();
  26.135 - *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
  26.136 - *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
  26.137 - *       }
  26.138 - *     }
  26.139 - *     // class Main { public static void main(String... av) { ...
  26.140 - *     final Number[] stuff = { 123, 456 };
  26.141 - *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
  26.142 - *         public Number get(long i)           { return stuff[(int)i]; }
  26.143 - *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
  26.144 - *     }
  26.145 - *     int x = (Integer) stuffPtr.&lt;Number&gt;invokeExact(1L);  // 456
  26.146 - *     stuffPtr.setter().&lt;void&gt;invokeExact(0L, (Number) 789);  // replaces 123 with 789
  26.147 - * </pre></blockquote>
  26.148 - * @see MethodHandle
  26.149 - * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
  26.150 - * an interface-based API for mixing method handle behavior with other classes.
  26.151 - * @author John Rose, JSR 292 EG
  26.152 - */
  26.153 -public abstract class JavaMethodHandle
  26.154 -        // Note: This is an implementation inheritance hack, and will be removed
  26.155 -        // with a JVM change which moves the required hidden behavior onto this class.
  26.156 -        extends sun.dyn.BoundMethodHandle
  26.157 -{
  26.158 -    private static final Access IMPL_TOKEN = Access.getToken();
  26.159 -
  26.160 -    /**
  26.161 -     * When creating a {@code JavaMethodHandle}, the actual method handle
  26.162 -     * invocation behavior will be delegated to the specified {@code entryPoint}.
  26.163 -     * This may be any method handle which can take the newly constructed object
  26.164 -     * as a leading parameter.
  26.165 -     * <p>
  26.166 -     * The method handle type of {@code this} (i.e, the fully constructed object)
  26.167 -     * will be {@code entryPoint}, minus the leading argument.
  26.168 -     * The leading argument will be bound to {@code this} on every method
  26.169 -     * handle invocation.
  26.170 -     * @param entryPoint the method handle to handle calls
  26.171 -     */
  26.172 -    protected JavaMethodHandle(MethodHandle entryPoint) {
  26.173 -        super(entryPoint);
  26.174 -    }
  26.175 -}
    27.1 --- a/src/share/classes/sun/dyn/MethodHandleImpl.java	Tue Dec 21 15:27:55 2010 -0800
    27.2 +++ b/src/share/classes/sun/dyn/MethodHandleImpl.java	Tue Dec 21 18:45:45 2010 -0800
    27.3 @@ -199,7 +199,7 @@
    27.4          return allocator;
    27.5      }
    27.6  
    27.7 -    static final class AllocateObject<C> extends JavaMethodHandle {
    27.8 +    static final class AllocateObject<C> extends BoundMethodHandle {
    27.9          private static final Unsafe unsafe = Unsafe.getUnsafe();
   27.10  
   27.11          private final Class<C> allocateClass;
   27.12 @@ -207,7 +207,7 @@
   27.13  
   27.14          private AllocateObject(MethodHandle invoker,
   27.15                                 Class<C> allocateClass, MethodHandle rawConstructor) {
   27.16 -            super(invoker);
   27.17 +            super(Access.TOKEN, invoker);
   27.18              this.allocateClass = allocateClass;
   27.19              this.rawConstructor = rawConstructor;
   27.20          }
   27.21 @@ -237,7 +237,7 @@
   27.22          }
   27.23          @Override
   27.24          public String toString() {
   27.25 -            return allocateClass.getSimpleName();
   27.26 +            return addTypeString(allocateClass.getSimpleName(), this);
   27.27          }
   27.28          @SuppressWarnings("unchecked")
   27.29          private C allocate() throws InstantiationException {
   27.30 @@ -245,52 +245,52 @@
   27.31          }
   27.32          private C invoke_V(Object... av) throws Throwable {
   27.33              C obj = allocate();
   27.34 -            rawConstructor.<void>invokeExact((Object)obj, av);
   27.35 +            rawConstructor.invokeExact((Object)obj, av);
   27.36              return obj;
   27.37          }
   27.38          private C invoke_L0() throws Throwable {
   27.39              C obj = allocate();
   27.40 -            rawConstructor.<void>invokeExact((Object)obj);
   27.41 +            rawConstructor.invokeExact((Object)obj);
   27.42              return obj;
   27.43          }
   27.44          private C invoke_L1(Object a0) throws Throwable {
   27.45              C obj = allocate();
   27.46 -            rawConstructor.<void>invokeExact((Object)obj, a0);
   27.47 +            rawConstructor.invokeExact((Object)obj, a0);
   27.48              return obj;
   27.49          }
   27.50          private C invoke_L2(Object a0, Object a1) throws Throwable {
   27.51              C obj = allocate();
   27.52 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1);
   27.53 +            rawConstructor.invokeExact((Object)obj, a0, a1);
   27.54              return obj;
   27.55          }
   27.56          private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
   27.57              C obj = allocate();
   27.58 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2);
   27.59 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2);
   27.60              return obj;
   27.61          }
   27.62          private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
   27.63              C obj = allocate();
   27.64 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3);
   27.65 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
   27.66              return obj;
   27.67          }
   27.68          private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
   27.69              C obj = allocate();
   27.70 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4);
   27.71 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
   27.72              return obj;
   27.73          }
   27.74          private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
   27.75              C obj = allocate();
   27.76 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
   27.77 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
   27.78              return obj;
   27.79          }
   27.80          private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
   27.81              C obj = allocate();
   27.82 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
   27.83 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
   27.84              return obj;
   27.85          }
   27.86          private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
   27.87              C obj = allocate();
   27.88 -            rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
   27.89 +            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
   27.90              return obj;
   27.91          }
   27.92          static MethodHandle[] makeInvokes() {
   27.93 @@ -369,19 +369,19 @@
   27.94          return mhs[isSetter ? 1 : 0];
   27.95      }
   27.96  
   27.97 -    static final class FieldAccessor<C,V> extends JavaMethodHandle {
   27.98 +    static final class FieldAccessor<C,V> extends BoundMethodHandle {
   27.99          private static final Unsafe unsafe = Unsafe.getUnsafe();
  27.100          final Object base;  // for static refs only
  27.101          final long offset;
  27.102          final String name;
  27.103  
  27.104          public FieldAccessor(Access token, MemberName field, boolean isSetter) {
  27.105 -            super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
  27.106 +            super(Access.TOKEN, fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
  27.107              this.offset = (long) field.getVMIndex(token);
  27.108              this.name = field.getName();
  27.109              this.base = staticBase(field);
  27.110          }
  27.111 -        public String toString() { return name; }
  27.112 +        public String toString() { return addTypeString(name, this); }
  27.113  
  27.114          int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
  27.115          void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
  27.116 @@ -560,7 +560,9 @@
  27.117      MethodHandle bindReceiver(Access token,
  27.118                                MethodHandle target, Object receiver) {
  27.119          Access.check(token);
  27.120 -        if (target instanceof AdapterMethodHandle) {
  27.121 +        if (target instanceof AdapterMethodHandle &&
  27.122 +            ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
  27.123 +            ) {
  27.124              Object info = MethodHandleNatives.getTargetInfo(target);
  27.125              if (info instanceof DirectMethodHandle) {
  27.126                  DirectMethodHandle dmh = (DirectMethodHandle) info;
  27.127 @@ -908,11 +910,11 @@
  27.128          throw new UnsupportedOperationException("NYI");
  27.129      }
  27.130  
  27.131 -    private static class GuardWithTest extends JavaMethodHandle {
  27.132 +    private static class GuardWithTest extends BoundMethodHandle {
  27.133          private final MethodHandle test, target, fallback;
  27.134          private GuardWithTest(MethodHandle invoker,
  27.135                                MethodHandle test, MethodHandle target, MethodHandle fallback) {
  27.136 -            super(invoker);
  27.137 +            super(Access.TOKEN, invoker);
  27.138              this.test = test;
  27.139              this.target = target;
  27.140              this.fallback = fallback;
  27.141 @@ -946,57 +948,57 @@
  27.142          }
  27.143          @Override
  27.144          public String toString() {
  27.145 -            return target.toString();
  27.146 +            return addTypeString(target, this);
  27.147          }
  27.148          private Object invoke_V(Object... av) throws Throwable {
  27.149 -            if (test.<boolean>invokeExact(av))
  27.150 -                return target.<Object>invokeExact(av);
  27.151 -            return fallback.<Object>invokeExact(av);
  27.152 +            if ((boolean) test.invokeExact(av))
  27.153 +                return target.invokeExact(av);
  27.154 +            return fallback.invokeExact(av);
  27.155          }
  27.156          private Object invoke_L0() throws Throwable {
  27.157 -            if (test.<boolean>invokeExact())
  27.158 -                return target.<Object>invokeExact();
  27.159 -            return fallback.<Object>invokeExact();
  27.160 +            if ((boolean) test.invokeExact())
  27.161 +                return target.invokeExact();
  27.162 +            return fallback.invokeExact();
  27.163          }
  27.164          private Object invoke_L1(Object a0) throws Throwable {
  27.165 -            if (test.<boolean>invokeExact(a0))
  27.166 -                return target.<Object>invokeExact(a0);
  27.167 -            return fallback.<Object>invokeExact(a0);
  27.168 +            if ((boolean) test.invokeExact(a0))
  27.169 +                return target.invokeExact(a0);
  27.170 +            return fallback.invokeExact(a0);
  27.171          }
  27.172          private Object invoke_L2(Object a0, Object a1) throws Throwable {
  27.173 -            if (test.<boolean>invokeExact(a0, a1))
  27.174 -                return target.<Object>invokeExact(a0, a1);
  27.175 -            return fallback.<Object>invokeExact(a0, a1);
  27.176 +            if ((boolean) test.invokeExact(a0, a1))
  27.177 +                return target.invokeExact(a0, a1);
  27.178 +            return fallback.invokeExact(a0, a1);
  27.179          }
  27.180          private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
  27.181 -            if (test.<boolean>invokeExact(a0, a1, a2))
  27.182 -                return target.<Object>invokeExact(a0, a1, a2);
  27.183 -            return fallback.<Object>invokeExact(a0, a1, a2);
  27.184 +            if ((boolean) test.invokeExact(a0, a1, a2))
  27.185 +                return target.invokeExact(a0, a1, a2);
  27.186 +            return fallback.invokeExact(a0, a1, a2);
  27.187          }
  27.188          private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
  27.189 -            if (test.<boolean>invokeExact(a0, a1, a2, a3))
  27.190 -                return target.<Object>invokeExact(a0, a1, a2, a3);
  27.191 -            return fallback.<Object>invokeExact(a0, a1, a2, a3);
  27.192 +            if ((boolean) test.invokeExact(a0, a1, a2, a3))
  27.193 +                return target.invokeExact(a0, a1, a2, a3);
  27.194 +            return fallback.invokeExact(a0, a1, a2, a3);
  27.195          }
  27.196          private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
  27.197 -            if (test.<boolean>invokeExact(a0, a1, a2, a3, a4))
  27.198 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4);
  27.199 -            return fallback.<Object>invokeExact(a0, a1, a2, a3, a4);
  27.200 +            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
  27.201 +                return target.invokeExact(a0, a1, a2, a3, a4);
  27.202 +            return fallback.invokeExact(a0, a1, a2, a3, a4);
  27.203          }
  27.204          private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
  27.205 -            if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5))
  27.206 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
  27.207 -            return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
  27.208 +            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
  27.209 +                return target.invokeExact(a0, a1, a2, a3, a4, a5);
  27.210 +            return fallback.invokeExact(a0, a1, a2, a3, a4, a5);
  27.211          }
  27.212          private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
  27.213 -            if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6))
  27.214 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.215 -            return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.216 +            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
  27.217 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.218 +            return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.219          }
  27.220          private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
  27.221 -            if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
  27.222 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.223 -            return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.224 +            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
  27.225 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.226 +            return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.227          }
  27.228          static MethodHandle[] makeInvokes() {
  27.229              ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
  27.230 @@ -1036,7 +1038,7 @@
  27.231          return GuardWithTest.make(token, test, target, fallback);
  27.232      }
  27.233  
  27.234 -    private static class GuardWithCatch extends JavaMethodHandle {
  27.235 +    private static class GuardWithCatch extends BoundMethodHandle {
  27.236          private final MethodHandle target;
  27.237          private final Class<? extends Throwable> exType;
  27.238          private final MethodHandle catcher;
  27.239 @@ -1045,93 +1047,93 @@
  27.240          }
  27.241          public GuardWithCatch(MethodHandle invoker,
  27.242                                MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
  27.243 -            super(invoker);
  27.244 +            super(Access.TOKEN, invoker);
  27.245              this.target = target;
  27.246              this.exType = exType;
  27.247              this.catcher = catcher;
  27.248          }
  27.249          @Override
  27.250          public String toString() {
  27.251 -            return target.toString();
  27.252 +            return addTypeString(target, this);
  27.253          }
  27.254          private Object invoke_V(Object... av) throws Throwable {
  27.255              try {
  27.256 -                return target.<Object>invokeExact(av);
  27.257 +                return target.invokeExact(av);
  27.258              } catch (Throwable t) {
  27.259                  if (!exType.isInstance(t))  throw t;
  27.260 -                return catcher.<Object>invokeExact(t, av);
  27.261 +                return catcher.invokeExact(t, av);
  27.262              }
  27.263          }
  27.264          private Object invoke_L0() throws Throwable {
  27.265              try {
  27.266 -                return target.<Object>invokeExact();
  27.267 +                return target.invokeExact();
  27.268              } catch (Throwable t) {
  27.269                  if (!exType.isInstance(t))  throw t;
  27.270 -                return catcher.<Object>invokeExact(t);
  27.271 +                return catcher.invokeExact(t);
  27.272              }
  27.273          }
  27.274          private Object invoke_L1(Object a0) throws Throwable {
  27.275              try {
  27.276 -                return target.<Object>invokeExact(a0);
  27.277 +                return target.invokeExact(a0);
  27.278              } catch (Throwable t) {
  27.279                  if (!exType.isInstance(t))  throw t;
  27.280 -                return catcher.<Object>invokeExact(t, a0);
  27.281 +                return catcher.invokeExact(t, a0);
  27.282              }
  27.283          }
  27.284          private Object invoke_L2(Object a0, Object a1) throws Throwable {
  27.285              try {
  27.286 -                return target.<Object>invokeExact(a0, a1);
  27.287 +                return target.invokeExact(a0, a1);
  27.288              } catch (Throwable t) {
  27.289                  if (!exType.isInstance(t))  throw t;
  27.290 -                return catcher.<Object>invokeExact(t, a0, a1);
  27.291 +                return catcher.invokeExact(t, a0, a1);
  27.292              }
  27.293          }
  27.294          private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
  27.295              try {
  27.296 -                return target.<Object>invokeExact(a0, a1, a2);
  27.297 +                return target.invokeExact(a0, a1, a2);
  27.298              } catch (Throwable t) {
  27.299                  if (!exType.isInstance(t))  throw t;
  27.300 -                return catcher.<Object>invokeExact(t, a0, a1, a2);
  27.301 +                return catcher.invokeExact(t, a0, a1, a2);
  27.302              }
  27.303          }
  27.304          private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
  27.305              try {
  27.306 -                return target.<Object>invokeExact(a0, a1, a2, a3);
  27.307 +                return target.invokeExact(a0, a1, a2, a3);
  27.308              } catch (Throwable t) {
  27.309                  if (!exType.isInstance(t))  throw t;
  27.310 -                return catcher.<Object>invokeExact(t, a0, a1, a2, a3);
  27.311 +                return catcher.invokeExact(t, a0, a1, a2, a3);
  27.312              }
  27.313          }
  27.314          private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
  27.315              try {
  27.316 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4);
  27.317 +                return target.invokeExact(a0, a1, a2, a3, a4);
  27.318              } catch (Throwable t) {
  27.319                  if (!exType.isInstance(t))  throw t;
  27.320 -                return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4);
  27.321 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4);
  27.322              }
  27.323          }
  27.324          private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
  27.325              try {
  27.326 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
  27.327 +                return target.invokeExact(a0, a1, a2, a3, a4, a5);
  27.328              } catch (Throwable t) {
  27.329                  if (!exType.isInstance(t))  throw t;
  27.330 -                return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5);
  27.331 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
  27.332              }
  27.333          }
  27.334          private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
  27.335              try {
  27.336 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.337 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
  27.338              } catch (Throwable t) {
  27.339                  if (!exType.isInstance(t))  throw t;
  27.340 -                return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
  27.341 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
  27.342              }
  27.343          }
  27.344          private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
  27.345              try {
  27.346 -                return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.347 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  27.348              } catch (Throwable t) {
  27.349                  if (!exType.isInstance(t))  throw t;
  27.350 -                return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
  27.351 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
  27.352              }
  27.353          }
  27.354          static MethodHandle[] makeInvokes() {
  27.355 @@ -1217,21 +1219,24 @@
  27.356          if (target != null)
  27.357              name = MethodHandleNatives.getMethodName(target);
  27.358          if (name == null)
  27.359 -            return "<unknown>";
  27.360 -        return name.getName();
  27.361 +            return "invoke" + target.type();
  27.362 +        return name.getName() + target.type();
  27.363      }
  27.364  
  27.365 -    public static String addTypeString(MethodHandle target) {
  27.366 -        if (target == null)  return "null";
  27.367 -        return target.toString() + target.type();
  27.368 +    static String addTypeString(Object obj, MethodHandle target) {
  27.369 +        String str = String.valueOf(obj);
  27.370 +        if (target == null)  return str;
  27.371 +        int paren = str.indexOf('(');
  27.372 +        if (paren >= 0) str = str.substring(0, paren);
  27.373 +        return str + target.type();
  27.374      }
  27.375  
  27.376 -    public static void checkSpreadArgument(Object av, int n) {
  27.377 +    static void checkSpreadArgument(Object av, int n) {
  27.378          if (av == null ? n != 0 : ((Object[])av).length != n)
  27.379              throw newIllegalArgumentException("Array is not of length "+n);
  27.380      }
  27.381  
  27.382 -    public static void raiseException(int code, Object actual, Object required) {
  27.383 +    static void raiseException(int code, Object actual, Object required) {
  27.384          String message;
  27.385          // disregard the identity of the actual object, if it is not a class:
  27.386          if (!(actual instanceof Class) && !(actual instanceof MethodType))
  27.387 @@ -1257,4 +1262,9 @@
  27.388          Access.check(token);
  27.389          return MethodHandleNatives.getBootstrap(callerClass);
  27.390      }
  27.391 +
  27.392 +    public static MethodHandle withTypeHandler(Access token, MethodHandle target, MethodHandle typeHandler) {
  27.393 +        Access.check(token);
  27.394 +        return AdapterMethodHandle.makeTypeHandler(token, target, typeHandler);
  27.395 +    }
  27.396  }
    28.1 --- a/src/share/classes/sun/dyn/MethodHandleNatives.java	Tue Dec 21 15:27:55 2010 -0800
    28.2 +++ b/src/share/classes/sun/dyn/MethodHandleNatives.java	Tue Dec 21 18:45:45 2010 -0800
    28.3 @@ -317,6 +317,20 @@
    28.4      }
    28.5  
    28.6      /**
    28.7 +     * The JVM wants to use a MethodType with invokeGeneric.  Give the runtime fair warning.
    28.8 +     */
    28.9 +    static void notifyGenericMethodType(MethodType type) {
   28.10 +        try {
   28.11 +            // Trigger adapter creation.
   28.12 +            InvokeGeneric.genericInvokerOf(type);
   28.13 +        } catch (Exception ex) {
   28.14 +            Error err = new InternalError("Exception while resolving invokeGeneric");
   28.15 +            err.initCause(ex);
   28.16 +            throw err;
   28.17 +        }
   28.18 +    }
   28.19 +
   28.20 +    /**
   28.21       * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
   28.22       * It will make an up-call to this method.  (Do not change the name or signature.)
   28.23       */
    29.1 --- a/src/share/classes/sun/dyn/MethodTypeImpl.java	Tue Dec 21 15:27:55 2010 -0800
    29.2 +++ b/src/share/classes/sun/dyn/MethodTypeImpl.java	Tue Dec 21 18:45:45 2010 -0800
    29.3 @@ -48,6 +48,7 @@
    29.4      final long primCounts;              // packed prim & double counts
    29.5      final int vmslots;                  // total number of parameter slots
    29.6      final MethodType erasedType;        // the canonical erasure
    29.7 +
    29.8      /*lazy*/ MethodType primsAsBoxes;   // replace prims by wrappers
    29.9      /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
   29.10      /*lazy*/ MethodType primsAsInts;    // replace prims by int/long
   29.11 @@ -59,6 +60,7 @@
   29.12      /*lazy*/ FromGeneric fromGeneric;   // convert cs. w/o prims to with
   29.13      /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
   29.14      /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
   29.15 +    /*lazy*/ MethodHandle genericInvoker; // hook for invokeGeneric
   29.16  
   29.17      public MethodType erasedType() {
   29.18          return erasedType;
    30.1 --- a/src/share/classes/sun/dyn/SpreadGeneric.java	Tue Dec 21 15:27:55 2010 -0800
    30.2 +++ b/src/share/classes/sun/dyn/SpreadGeneric.java	Tue Dec 21 18:45:45 2010 -0800
    30.3 @@ -208,7 +208,7 @@
    30.4       * The invoker is kept separate from the target because it can be
    30.5       * generated once per type erasure family, and reused across adapters.
    30.6       */
    30.7 -    static abstract class Adapter extends JavaMethodHandle {
    30.8 +    static abstract class Adapter extends BoundMethodHandle {
    30.9          /*
   30.10           * class X<<R,int M,int N>> extends Adapter {
   30.11           *   (Object**N)=>R target;
   30.12 @@ -221,21 +221,21 @@
   30.13  
   30.14          @Override
   30.15          public String toString() {
   30.16 -            return target.toString();
   30.17 +            return MethodHandleImpl.addTypeString(target, this);
   30.18          }
   30.19  
   30.20          static final MethodHandle NO_ENTRY = ValueConversions.identity();
   30.21  
   30.22          protected boolean isPrototype() { return target == null; }
   30.23          protected Adapter(SpreadGeneric outer) {
   30.24 -            super(NO_ENTRY);
   30.25 +            super(Access.TOKEN, NO_ENTRY);
   30.26              this.outer = outer;
   30.27              this.target = null;
   30.28              assert(isPrototype());
   30.29          }
   30.30  
   30.31          protected Adapter(SpreadGeneric outer, MethodHandle target) {
   30.32 -            super(outer.entryPoint);
   30.33 +            super(Access.TOKEN, outer.entryPoint);
   30.34              this.outer = outer;
   30.35              this.target = target;
   30.36          }
   30.37 @@ -277,12 +277,12 @@
   30.38          protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
   30.39          protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
   30.40          protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
   30.41 -             return target.<Object>invokeExact(a0, a1)); }
   30.42 +             return target.invokeExact(a0, a1)); }
   30.43          protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
   30.44 -             return target.<Object>invokeExact(a0,
   30.45 +             return target.invokeExact(a0,
   30.46                  super.select(av,0)); }
   30.47          protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
   30.48 -             return target.<Object>invokeExact(
   30.49 +             return target.invokeExact(
   30.50                  super.select(av,0), super.select(av,1)); }
   30.51      }
   30.52      // */
   30.53 @@ -300,10 +300,10 @@
   30.54          "        protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
   30.55          "        protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
   30.56          "        protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
   30.57 -        "            return target.<Object>invokeExact(@av@); }",
   30.58 +        "            return target.invokeExact(@av@); }",
   30.59          "        //@each-S@",
   30.60          "        protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
   30.61 -        "            return target.<Object>invokeExact(@av,@@sv@); }",
   30.62 +        "            return target.invokeExact(@av,@@sv@); }",
   30.63          "        //@end-S@",
   30.64          "    }",
   30.65      } };
   30.66 @@ -414,16 +414,16 @@
   30.67          protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
   30.68          protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
   30.69          protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
   30.70 -            return target.<Object>invokeExact(); }
   30.71 +            return target.invokeExact(); }
   30.72      }
   30.73      static class S1 extends Adapter {
   30.74          protected S1(SpreadGeneric outer) { super(outer); }  // to build prototype
   30.75          protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
   30.76          protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
   30.77          protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
   30.78 -            return target.<Object>invokeExact(a0); }
   30.79 +            return target.invokeExact(a0); }
   30.80          protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
   30.81 -            return target.<Object>invokeExact(
   30.82 +            return target.invokeExact(
   30.83                  super.select(av,0)); }
   30.84      }
   30.85      static class S2 extends Adapter {
   30.86 @@ -431,12 +431,12 @@
   30.87          protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
   30.88          protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
   30.89          protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
   30.90 -            return target.<Object>invokeExact(a0, a1); }
   30.91 +            return target.invokeExact(a0, a1); }
   30.92          protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
   30.93 -            return target.<Object>invokeExact(a0,
   30.94 +            return target.invokeExact(a0,
   30.95                  super.select(av,0)); }
   30.96          protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
   30.97 -            return target.<Object>invokeExact(
   30.98 +            return target.invokeExact(
   30.99                  super.select(av,0), super.select(av,1)); }
  30.100      }
  30.101      static class S3 extends Adapter {
  30.102 @@ -444,15 +444,15 @@
  30.103          protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.104          protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
  30.105          protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
  30.106 -            return target.<Object>invokeExact(a0, a1, a2); }
  30.107 +            return target.invokeExact(a0, a1, a2); }
  30.108          protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
  30.109 -            return target.<Object>invokeExact(a0, a1,
  30.110 +            return target.invokeExact(a0, a1,
  30.111                  super.select(av,0)); }
  30.112          protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
  30.113 -            return target.<Object>invokeExact(a0,
  30.114 +            return target.invokeExact(a0,
  30.115                  super.select(av,0), super.select(av,1)); }
  30.116          protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
  30.117 -            return target.<Object>invokeExact(
  30.118 +            return target.invokeExact(
  30.119                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.120      }
  30.121      static class S4 extends Adapter {
  30.122 @@ -460,18 +460,18 @@
  30.123          protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.124          protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
  30.125          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
  30.126 -            return target.<Object>invokeExact(a0, a1, a2, a3); }
  30.127 +            return target.invokeExact(a0, a1, a2, a3); }
  30.128          protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
  30.129 -            return target.<Object>invokeExact(a0, a1, a2,
  30.130 +            return target.invokeExact(a0, a1, a2,
  30.131                  super.select(av,0)); }
  30.132          protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
  30.133 -            return target.<Object>invokeExact(a0, a1,
  30.134 +            return target.invokeExact(a0, a1,
  30.135                  super.select(av,0), super.select(av,1)); }
  30.136          protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
  30.137 -            return target.<Object>invokeExact(a0,
  30.138 +            return target.invokeExact(a0,
  30.139                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.140          protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
  30.141 -            return target.<Object>invokeExact(
  30.142 +            return target.invokeExact(
  30.143                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.144      }
  30.145      static class S5 extends Adapter {
  30.146 @@ -479,21 +479,21 @@
  30.147          protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.148          protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
  30.149          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
  30.150 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4); }
  30.151 +            return target.invokeExact(a0, a1, a2, a3, a4); }
  30.152          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
  30.153 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.154 +            return target.invokeExact(a0, a1, a2, a3,
  30.155                  super.select(av,0)); }
  30.156          protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
  30.157 -            return target.<Object>invokeExact(a0, a1, a2,
  30.158 +            return target.invokeExact(a0, a1, a2,
  30.159                  super.select(av,0), super.select(av,1)); }
  30.160          protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
  30.161 -            return target.<Object>invokeExact(a0, a1,
  30.162 +            return target.invokeExact(a0, a1,
  30.163                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.164          protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
  30.165 -            return target.<Object>invokeExact(a0,
  30.166 +            return target.invokeExact(a0,
  30.167                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.168          protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
  30.169 -            return target.<Object>invokeExact(
  30.170 +            return target.invokeExact(
  30.171                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.172                  super.select(av,4)); }
  30.173      }
  30.174 @@ -502,25 +502,25 @@
  30.175          protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.176          protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
  30.177          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
  30.178 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5); }
  30.179 +            return target.invokeExact(a0, a1, a2, a3, a4, a5); }
  30.180          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
  30.181 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4,
  30.182 +            return target.invokeExact(a0, a1, a2, a3, a4,
  30.183                  super.select(av,0)); }
  30.184          protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
  30.185 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.186 +            return target.invokeExact(a0, a1, a2, a3,
  30.187                  super.select(av,0), super.select(av,1)); }
  30.188          protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
  30.189 -            return target.<Object>invokeExact(a0, a1, a2,
  30.190 +            return target.invokeExact(a0, a1, a2,
  30.191                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.192          protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
  30.193 -            return target.<Object>invokeExact(a0, a1,
  30.194 +            return target.invokeExact(a0, a1,
  30.195                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.196          protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
  30.197 -            return target.<Object>invokeExact(a0,
  30.198 +            return target.invokeExact(a0,
  30.199                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.200                  super.select(av,4)); }
  30.201          protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
  30.202 -            return target.<Object>invokeExact(
  30.203 +            return target.invokeExact(
  30.204                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.205                  super.select(av,4), super.select(av,5)); }
  30.206      }
  30.207 @@ -529,29 +529,29 @@
  30.208          protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.209          protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
  30.210          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
  30.211 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6); }
  30.212 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); }
  30.213          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
  30.214 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5,
  30.215 +            return target.invokeExact(a0, a1, a2, a3, a4, a5,
  30.216                  super.select(av,0)); }
  30.217          protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
  30.218 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4,
  30.219 +            return target.invokeExact(a0, a1, a2, a3, a4,
  30.220                  super.select(av,0), super.select(av,1)); }
  30.221          protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
  30.222 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.223 +            return target.invokeExact(a0, a1, a2, a3,
  30.224                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.225          protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
  30.226 -            return target.<Object>invokeExact(a0, a1, a2,
  30.227 +            return target.invokeExact(a0, a1, a2,
  30.228                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.229          protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
  30.230 -            return target.<Object>invokeExact(a0, a1,
  30.231 +            return target.invokeExact(a0, a1,
  30.232                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.233                  super.select(av,4)); }
  30.234          protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
  30.235 -            return target.<Object>invokeExact(a0,
  30.236 +            return target.invokeExact(a0,
  30.237                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.238                  super.select(av,4), super.select(av,5)); }
  30.239          protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
  30.240 -            return target.<Object>invokeExact(
  30.241 +            return target.invokeExact(
  30.242                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.243                  super.select(av,4), super.select(av,5), super.select(av,6)); }
  30.244      }
  30.245 @@ -560,33 +560,33 @@
  30.246          protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.247          protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
  30.248          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
  30.249 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); }
  30.250 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); }
  30.251          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
  30.252 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.253 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.254                  super.select(av,0)); }
  30.255          protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
  30.256 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5,
  30.257 +            return target.invokeExact(a0, a1, a2, a3, a4, a5,
  30.258                  super.select(av,0), super.select(av,1)); }
  30.259          protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
  30.260 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4,
  30.261 +            return target.invokeExact(a0, a1, a2, a3, a4,
  30.262                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.263          protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
  30.264 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.265 +            return target.invokeExact(a0, a1, a2, a3,
  30.266                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.267          protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
  30.268 -            return target.<Object>invokeExact(a0, a1, a2,
  30.269 +            return target.invokeExact(a0, a1, a2,
  30.270                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.271                  super.select(av,4)); }
  30.272          protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
  30.273 -            return target.<Object>invokeExact(a0, a1,
  30.274 +            return target.invokeExact(a0, a1,
  30.275                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.276                  super.select(av,4), super.select(av,5)); }
  30.277          protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
  30.278 -            return target.<Object>invokeExact(a0,
  30.279 +            return target.invokeExact(a0,
  30.280                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.281                  super.select(av,4), super.select(av,5), super.select(av,6)); }
  30.282          protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
  30.283 -            return target.<Object>invokeExact(
  30.284 +            return target.invokeExact(
  30.285                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.286                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
  30.287      }
  30.288 @@ -595,37 +595,37 @@
  30.289          protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.290          protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
  30.291          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
  30.292 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  30.293 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  30.294          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
  30.295 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
  30.296 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
  30.297                  super.select(av,0)); }
  30.298          protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
  30.299 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.300 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.301                  super.select(av,0), super.select(av,1)); }
  30.302          protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
  30.303 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5,
  30.304 +            return target.invokeExact(a0, a1, a2, a3, a4, a5,
  30.305                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.306          protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
  30.307 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4,
  30.308 +            return target.invokeExact(a0, a1, a2, a3, a4,
  30.309                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.310          protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
  30.311 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.312 +            return target.invokeExact(a0, a1, a2, a3,
  30.313                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.314                  super.select(av,4)); }
  30.315          protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
  30.316 -            return target.<Object>invokeExact(a0, a1, a2,
  30.317 +            return target.invokeExact(a0, a1, a2,
  30.318                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.319                  super.select(av,4), super.select(av,5)); }
  30.320          protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
  30.321 -            return target.<Object>invokeExact(a0, a1,
  30.322 +            return target.invokeExact(a0, a1,
  30.323                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.324                  super.select(av,4), super.select(av,5), super.select(av,6)); }
  30.325          protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
  30.326 -            return target.<Object>invokeExact(a0,
  30.327 +            return target.invokeExact(a0,
  30.328                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.329                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
  30.330          protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
  30.331 -            return target.<Object>invokeExact(
  30.332 +            return target.invokeExact(
  30.333                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.334                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
  30.335                  super.select(av,8)); }
  30.336 @@ -635,42 +635,42 @@
  30.337          protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
  30.338          protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
  30.339          protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
  30.340 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  30.341 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  30.342          protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
  30.343 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8,
  30.344 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8,
  30.345                  super.select(av,0)); }
  30.346          protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
  30.347 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
  30.348 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
  30.349                  super.select(av,0), super.select(av,1)); }
  30.350          protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
  30.351 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.352 +            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
  30.353                  super.select(av,0), super.select(av,1), super.select(av,2)); }
  30.354          protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
  30.355 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5,
  30.356 +            return target.invokeExact(a0, a1, a2, a3, a4, a5,
  30.357                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
  30.358          protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
  30.359 -            return target.<Object>invokeExact(a0, a1, a2, a3, a4,
  30.360 +            return target.invokeExact(a0, a1, a2, a3, a4,
  30.361                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.362                  super.select(av,4)); }
  30.363          protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
  30.364 -            return target.<Object>invokeExact(a0, a1, a2, a3,
  30.365 +            return target.invokeExact(a0, a1, a2, a3,
  30.366                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.367                  super.select(av,4), super.select(av,5)); }
  30.368          protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
  30.369 -            return target.<Object>invokeExact(a0, a1, a2,
  30.370 +            return target.invokeExact(a0, a1, a2,
  30.371                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.372                  super.select(av,4), super.select(av,5), super.select(av,6)); }
  30.373          protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
  30.374 -            return target.<Object>invokeExact(a0, a1,
  30.375 +            return target.invokeExact(a0, a1,
  30.376                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.377                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
  30.378          protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
  30.379 -            return target.<Object>invokeExact(a0,
  30.380 +            return target.invokeExact(a0,
  30.381                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.382                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
  30.383                  super.select(av,8)); }
  30.384          protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
  30.385 -            return target.<Object>invokeExact(
  30.386 +            return target.invokeExact(
  30.387                  super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
  30.388                  super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
  30.389                  super.select(av,8), super.select(av,9)); }
    31.1 --- a/src/share/classes/sun/dyn/ToGeneric.java	Tue Dec 21 15:27:55 2010 -0800
    31.2 +++ b/src/share/classes/sun/dyn/ToGeneric.java	Tue Dec 21 18:45:45 2010 -0800
    31.3 @@ -323,7 +323,7 @@
    31.4       * via another method handle {@code convert}, which is responsible for
    31.5       * converting the object result into the raw return value.
    31.6       */
    31.7 -    static abstract class Adapter extends JavaMethodHandle {
    31.8 +    static abstract class Adapter extends BoundMethodHandle {
    31.9          /*
   31.10           * class X<<R,A...>> extends Adapter {
   31.11           *   Object...=>Object target;
   31.12 @@ -337,13 +337,13 @@
   31.13  
   31.14          @Override
   31.15          public String toString() {
   31.16 -            return target == null ? "prototype:"+convert : target.toString();
   31.17 +            return target == null ? "prototype:"+convert : MethodHandleImpl.addTypeString(target, this);
   31.18          }
   31.19  
   31.20          protected boolean isPrototype() { return target == null; }
   31.21          /* Prototype constructor. */
   31.22          protected Adapter(MethodHandle entryPoint) {
   31.23 -            super(entryPoint);
   31.24 +            super(Access.TOKEN, entryPoint);
   31.25              this.invoker = null;
   31.26              this.convert = entryPoint;
   31.27              this.target = null;
   31.28 @@ -355,7 +355,7 @@
   31.29          }
   31.30  
   31.31          protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
   31.32 -            super(entryPoint);
   31.33 +            super(Access.TOKEN, entryPoint);
   31.34              this.invoker = invoker;
   31.35              this.convert = convert;
   31.36              this.target = target;
   31.37 @@ -367,33 +367,33 @@
   31.38          // { return new ThisType(entryPoint, convert, target); }
   31.39  
   31.40          // Code to run when the arguments (<= 4) have all been boxed.
   31.41 -        protected Object target()               throws Throwable { return invoker.<Object>invokeExact(target); }
   31.42 -        protected Object target(Object a0)      throws Throwable { return invoker.<Object>invokeExact(target, a0); }
   31.43 +        protected Object target()               throws Throwable { return invoker.invokeExact(target); }
   31.44 +        protected Object target(Object a0)      throws Throwable { return invoker.invokeExact(target, a0); }
   31.45          protected Object target(Object a0, Object a1)
   31.46 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1); }
   31.47 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1); }
   31.48          protected Object target(Object a0, Object a1, Object a2)
   31.49 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2); }
   31.50 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
   31.51          protected Object target(Object a0, Object a1, Object a2, Object a3)
   31.52 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3); }
   31.53 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
   31.54          /*
   31.55 -        protected Object target_0(Object... av) throws Throwable { return invoker.<Object>invokeExact(target, av); }
   31.56 +        protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); }
   31.57          protected Object target_1(Object a0, Object... av)
   31.58 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, (Object)av); }
   31.59 +                                                throws Throwable { return invoker.invokeExact(target, a0, (Object)av); }
   31.60          protected Object target_2(Object a0, Object a1, Object... av)
   31.61 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, (Object)av); }
   31.62 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); }
   31.63          protected Object target_3(Object a0, Object a1, Object a2, Object... av)
   31.64 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, (Object)av); }
   31.65 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); }
   31.66          protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
   31.67 -                                                throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, (Object)av); }
   31.68 +                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, (Object)av); }
   31.69          // */
   31.70          // (For more than 4 arguments, generate the code in the adapter itself.)
   31.71  
   31.72          // Code to run when the generic target has finished and produced a value.
   31.73 -        protected Object return_L(Object res) throws Throwable { return convert.<Object>invokeExact(res); }
   31.74 -        protected int    return_I(Object res) throws Throwable { return convert.<int   >invokeExact(res); }
   31.75 -        protected long   return_J(Object res) throws Throwable { return convert.<long  >invokeExact(res); }
   31.76 -        protected float  return_F(Object res) throws Throwable { return convert.<float >invokeExact(res); }
   31.77 -        protected double return_D(Object res) throws Throwable { return convert.<double>invokeExact(res); }
   31.78 +        protected Object return_L(Object res) throws Throwable { return (Object)convert.invokeExact(res); }
   31.79 +        protected int    return_I(Object res) throws Throwable { return (int)   convert.invokeExact(res); }
   31.80 +        protected long   return_J(Object res) throws Throwable { return (long)  convert.invokeExact(res); }
   31.81 +        protected float  return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
   31.82 +        protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
   31.83  
   31.84          static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
   31.85          static {
   31.86 @@ -420,7 +420,7 @@
   31.87          protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
   31.88          protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
   31.89          protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
   31.90 -        protected Object target(Object a0)   throws Throwable { return invoker.<Object>invokeExact(target, a0); }
   31.91 +        protected Object target(Object a0)   throws Throwable { return invoker.invokeExact(target, a0); }
   31.92          protected Object targetA1(Object a0) throws Throwable { return target(a0); }
   31.93          protected Object targetA1(int    a0) throws Throwable { return target(a0); }
   31.94          protected Object targetA1(long   a0) throws Throwable { return target(a0); }
   31.95 @@ -458,7 +458,7 @@
   31.96          "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
   31.97          "        protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
   31.98          "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
   31.99 -        "        protected Object target(@Ovav@)   throws Throwable { return invoker.<Object>invokeExact(target, @av@); }",
  31.100 +        "        protected Object target(@Ovav@)   throws Throwable { return invoker.invokeExact(target, @av@); }",
  31.101          "        //@each-Tv@",
  31.102          "        protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
  31.103          "        //@end-Tv@",
  31.104 @@ -618,7 +618,7 @@
  31.105          protected A0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.106          protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.107          protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
  31.108 -        protected Object target()   throws Throwable { return invoker.<Object>invokeExact(target); }
  31.109 +        protected Object target()   throws Throwable { return invoker.invokeExact(target); }
  31.110          protected Object targetA0() throws Throwable { return target(); }
  31.111          protected Object invoke_L() throws Throwable { return return_L(targetA0()); }
  31.112          protected int    invoke_I() throws Throwable { return return_I(targetA0()); }
  31.113 @@ -630,7 +630,7 @@
  31.114          protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.115          protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.116          protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
  31.117 -        protected Object target(Object a0)   throws Throwable { return invoker.<Object>invokeExact(target, a0); }
  31.118 +        protected Object target(Object a0)   throws Throwable { return invoker.invokeExact(target, a0); }
  31.119          protected Object targetA1(Object a0) throws Throwable { return target(a0); }
  31.120          protected Object targetA1(int    a0) throws Throwable { return target(a0); }
  31.121          protected Object targetA1(long   a0) throws Throwable { return target(a0); }
  31.122 @@ -654,7 +654,7 @@
  31.123          protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.124          protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.125          protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
  31.126 -        protected Object target(Object a0, Object a1)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1); }
  31.127 +        protected Object target(Object a0, Object a1)   throws Throwable { return invoker.invokeExact(target, a0, a1); }
  31.128          protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); }
  31.129          protected Object targetA2(Object a0, int    a1) throws Throwable { return target(a0, a1); }
  31.130          protected Object targetA2(int    a0, int    a1) throws Throwable { return target(a0, a1); }
  31.131 @@ -690,7 +690,7 @@
  31.132          protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.133          protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.134          protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
  31.135 -        protected Object target(Object a0, Object a1, Object a2)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2); }
  31.136 +        protected Object target(Object a0, Object a1, Object a2)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
  31.137          protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); }
  31.138          protected Object targetA3(Object a0, Object a1, int    a2) throws Throwable { return target(a0, a1, a2); }
  31.139          protected Object targetA3(Object a0, int    a1, int    a2) throws Throwable { return target(a0, a1, a2); }
  31.140 @@ -739,7 +739,7 @@
  31.141          protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.142          protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.143          protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
  31.144 -        protected Object target(Object a0, Object a1, Object a2, Object a3)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3); }
  31.145 +        protected Object target(Object a0, Object a1, Object a2, Object a3)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
  31.146          protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); }
  31.147          protected Object targetA4(Object a0, Object a1, Object a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
  31.148          protected Object targetA4(Object a0, Object a1, int    a2, int    a3) throws Throwable { return target(a0, a1, a2, a3); }
  31.149 @@ -781,7 +781,7 @@
  31.150          protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.151          protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.152          protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
  31.153 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4); }
  31.154 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4); }
  31.155          protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
  31.156          protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
  31.157          protected Object targetA5(Object a0, Object a1, Object a2, int    a3, int    a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
  31.158 @@ -832,7 +832,7 @@
  31.159          protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.160          protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.161          protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
  31.162 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5); }
  31.163 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5); }
  31.164          protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
  31.165          protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
  31.166          protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
  31.167 @@ -866,7 +866,7 @@
  31.168          protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.169          protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.170          protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
  31.171 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6); }
  31.172 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6); }
  31.173          protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
  31.174          protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
  31.175          protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
  31.176 @@ -904,7 +904,7 @@
  31.177          protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.178          protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.179          protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
  31.180 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); }
  31.181 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); }
  31.182          protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  31.183          protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  31.184          protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  31.185 @@ -946,7 +946,7 @@
  31.186          protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.187          protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.188          protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
  31.189 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  31.190 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  31.191          protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  31.192          protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  31.193          protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  31.194 @@ -992,7 +992,7 @@
  31.195          protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  31.196          protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  31.197          protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
  31.198 -        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9)   throws Throwable { return invoker.<Object>invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  31.199 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9)   throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  31.200          protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  31.201          protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  31.202          protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
    32.1 --- a/src/share/classes/sun/dyn/util/ValueConversions.java	Tue Dec 21 15:27:55 2010 -0800
    32.2 +++ b/src/share/classes/sun/dyn/util/ValueConversions.java	Tue Dec 21 18:45:45 2010 -0800
    32.3 @@ -377,7 +377,7 @@
    32.4              REBOX_CONVERSIONS = newWrapperCaches(2);
    32.5  
    32.6      /**
    32.7 -     * Becase we normalize primitive types to reduce the number of signatures,
    32.8 +     * Because we normalize primitive types to reduce the number of signatures,
    32.9       * primitives are sometimes manipulated under an "erased" type,
   32.10       * either int (for types other than long/double) or long (for all types).
   32.11       * When the erased primitive value is then boxed into an Integer or Long,
   32.12 @@ -475,10 +475,10 @@
   32.13      }
   32.14  
   32.15      private static final EnumMap<Wrapper, MethodHandle>[]
   32.16 -            ZERO_CONSTANT_FUNCTIONS = newWrapperCaches(1);
   32.17 +            CONSTANT_FUNCTIONS = newWrapperCaches(2);
   32.18  
   32.19      public static MethodHandle zeroConstantFunction(Wrapper wrap) {
   32.20 -        EnumMap<Wrapper, MethodHandle> cache = ZERO_CONSTANT_FUNCTIONS[0];
   32.21 +        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
   32.22          MethodHandle mh = cache.get(wrap);
   32.23          if (mh != null) {
   32.24              return mh;
   32.25 @@ -544,6 +544,24 @@
   32.26      }
   32.27  
   32.28      /**
   32.29 +     * Identity function on ints.
   32.30 +     * @param x an arbitrary int value
   32.31 +     * @return the same value x
   32.32 +     */
   32.33 +    static int identity(int x) {
   32.34 +        return x;
   32.35 +    }
   32.36 +
   32.37 +    /**
   32.38 +     * Identity function on longs.
   32.39 +     * @param x an arbitrary long value
   32.40 +     * @return the same value x
   32.41 +     */
   32.42 +    static long identity(long x) {
   32.43 +        return x;
   32.44 +    }
   32.45 +
   32.46 +    /**
   32.47       * Identity function, with reference cast.
   32.48       * @param t an arbitrary reference type
   32.49       * @param x an arbitrary reference value
   32.50 @@ -553,7 +571,7 @@
   32.51          return t.cast(x);
   32.52      }
   32.53  
   32.54 -    private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
   32.55 +    private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
   32.56      static {
   32.57          try {
   32.58              MethodType idType = MethodType.genericMethodType(1);
   32.59 @@ -562,6 +580,8 @@
   32.60              MethodType ignoreType = idType.changeReturnType(void.class);
   32.61              MethodType zeroObjectType = MethodType.genericMethodType(0);
   32.62              IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
   32.63 +            IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class));
   32.64 +            IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class));
   32.65              //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
   32.66              CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
   32.67              ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
   32.68 @@ -613,8 +633,53 @@
   32.69          return IDENTITY;
   32.70      }
   32.71  
   32.72 +    public static MethodHandle identity(Class<?> type) {
   32.73 +        if (type == Object.class)
   32.74 +            return IDENTITY;
   32.75 +        else if (!type.isPrimitive())
   32.76 +            return retype(MethodType.methodType(type, type), IDENTITY);
   32.77 +        else
   32.78 +            return identity(Wrapper.forPrimitiveType(type));
   32.79 +    }
   32.80 +
   32.81 +    static MethodHandle identity(Wrapper wrap) {
   32.82 +        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
   32.83 +        MethodHandle mh = cache.get(wrap);
   32.84 +        if (mh != null) {
   32.85 +            return mh;
   32.86 +        }
   32.87 +        // slow path
   32.88 +        MethodType type = MethodType.methodType(wrap.primitiveType());
   32.89 +        if (wrap != Wrapper.VOID)
   32.90 +            type = type.appendParameterTypes(wrap.primitiveType());
   32.91 +        try {
   32.92 +            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type);
   32.93 +        } catch (NoAccessException ex) {
   32.94 +            mh = null;
   32.95 +        }
   32.96 +        if (mh == null && wrap == Wrapper.VOID) {
   32.97 +            mh = EMPTY;  // #(){} : #()void
   32.98 +        }
   32.99 +        if (mh != null) {
  32.100 +            cache.put(wrap, mh);
  32.101 +            return mh;
  32.102 +        }
  32.103 +
  32.104 +        // use a raw conversion
  32.105 +        if (wrap.isSingleWord() && wrap != Wrapper.INT) {
  32.106 +            mh = retype(type, identity(Wrapper.INT));
  32.107 +        } else if (wrap.isDoubleWord() && wrap != Wrapper.LONG) {
  32.108 +            mh = retype(type, identity(Wrapper.LONG));
  32.109 +        }
  32.110 +        if (mh != null) {
  32.111 +            cache.put(wrap, mh);
  32.112 +            return mh;
  32.113 +        }
  32.114 +        throw new IllegalArgumentException("cannot find identity for " + wrap);
  32.115 +    }
  32.116 +
  32.117      private static MethodHandle retype(MethodType type, MethodHandle mh) {
  32.118 -        return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh);
  32.119 +        return AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, type, mh);
  32.120      }
  32.121  
  32.122      private static final Object[] NO_ARGS_ARRAY = {};
    33.1 --- a/src/share/classes/sun/dyn/util/VerifyAccess.java	Tue Dec 21 15:27:55 2010 -0800
    33.2 +++ b/src/share/classes/sun/dyn/util/VerifyAccess.java	Tue Dec 21 18:45:45 2010 -0800
    33.3 @@ -25,7 +25,6 @@
    33.4  
    33.5  package sun.dyn.util;
    33.6  
    33.7 -import java.dyn.LinkagePermission;
    33.8  import java.dyn.NoAccessException;
    33.9  import java.lang.reflect.Modifier;
   33.10  import sun.dyn.MemberName;
   33.11 @@ -43,6 +42,7 @@
   33.12  
   33.13      private static final int PACKAGE_ONLY = 0;
   33.14      private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
   33.15 +    private static final boolean ALLOW_NESTMATE_ACCESS = false;
   33.16  
   33.17      /**
   33.18       * Evaluate the JVM linkage rules for access to the given method
   33.19 @@ -102,6 +102,8 @@
   33.20                  // a superclass of the lookup class.
   33.21              }
   33.22          }
   33.23 +        if (defc == lookupClass)
   33.24 +            return true;        // easy check; all self-access is OK
   33.25          switch (mods & ALL_ACCESS_MODES) {
   33.26          case PUBLIC:
   33.27              if (refc != defc)  return true;  // already checked above
   33.28 @@ -112,7 +114,8 @@
   33.29              return isSamePackage(defc, lookupClass);
   33.30          case PRIVATE:
   33.31              // Loosened rules for privates follows access rules for inner classes.
   33.32 -            return isSamePackageMember(defc, lookupClass);
   33.33 +            return (ALLOW_NESTMATE_ACCESS &&
   33.34 +                    isSamePackageMember(defc, lookupClass));
   33.35          default:
   33.36              throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
   33.37          }
   33.38 @@ -206,24 +209,4 @@
   33.39          }
   33.40          return false;
   33.41      }
   33.42 -
   33.43 -    /**
   33.44 -     * Ensure the requesting class have privileges to perform invokedynamic
   33.45 -     * linkage operations on subjectClass.  True if requestingClass is
   33.46 -     * Access.class (meaning the request originates from the JVM) or if the
   33.47 -     * classes are in the same package and have consistent class loaders.
   33.48 -     * (The subject class loader must be identical with or be a child of
   33.49 -     * the requesting class loader.)
   33.50 -     * @param requestingClass
   33.51 -     * @param subjectClass
   33.52 -     */
   33.53 -    public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass,
   33.54 -                                               String permissionName) {
   33.55 -        if (requestingClass == null)          return;
   33.56 -        if (requestingClass == subjectClass)  return;
   33.57 -        SecurityManager security = System.getSecurityManager();
   33.58 -        if (security == null)  return;  // open season
   33.59 -        if (isSamePackage(requestingClass, subjectClass))  return;
   33.60 -        security.checkPermission(new LinkagePermission(permissionName, requestingClass));
   33.61 -    }
   33.62  }
    34.1 --- a/src/share/classes/sun/dyn/util/Wrapper.java	Tue Dec 21 15:27:55 2010 -0800
    34.2 +++ b/src/share/classes/sun/dyn/util/Wrapper.java	Tue Dec 21 18:45:45 2010 -0800
    34.3 @@ -26,17 +26,19 @@
    34.4  package sun.dyn.util;
    34.5  
    34.6  public enum Wrapper {
    34.7 -    INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
    34.8 -    LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
    34.9 +    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
   34.10 +    // These must be in the order defined for widening primitive conversions in JLS 5.1.2
   34.11      BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
   34.12      SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
   34.13      CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
   34.14 -    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
   34.15 +    INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
   34.16 +    LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
   34.17      FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
   34.18      DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
   34.19 -    VOID(Void.class, void.class, 'V', null, Format.other(0)),
   34.20      //NULL(Null.class, null.class, 'N', null, Format.other(1)),
   34.21      OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
   34.22 +    // VOID must be the last type, since it is "assignable" from any other type:
   34.23 +    VOID(Void.class, void.class, 'V', null, Format.other(0)),
   34.24      ;
   34.25  
   34.26      private final Class<?> wrapperType;
   34.27 @@ -76,9 +78,11 @@
   34.28                     false);
   34.29              return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
   34.30          }
   34.31 -        static int
   34.32 +        static final int
   34.33                  INT      = SIGNED   | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   34.34 +                SHORT    = SIGNED   | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   34.35                  BOOLEAN  = UNSIGNED | (1  << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   34.36 +                CHAR     = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   34.37                  FLOAT    = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   34.38                  VOID     = UNSIGNED | (0  << SIZE_SHIFT) | (0 << SLOT_SHIFT),
   34.39                  NUM_MASK = (-1) << SIZE_SHIFT;
   34.40 @@ -111,6 +115,29 @@
   34.41      /** Is the wrapped type either float or double? */
   34.42      public boolean isFloating()    { return format >= Format.FLOAT; }
   34.43  
   34.44 +    /** Does the JVM verifier allow a variable of this wrapper's
   34.45 +     *  primitive type to be assigned from a value of the given wrapper's primitive type?
   34.46 +     *  Cases:
   34.47 +     *  <ul>
   34.48 +     *  <li>unboxing followed by widening primitive conversion
   34.49 +     *  <li>any type converted to {@code void}
   34.50 +     *  <li>boxing conversion followed by widening reference conversion to {@code Object}
   34.51 +     *  <li>conversion of {@code boolean} to any type
   34.52 +     *  </ul>
   34.53 +     */
   34.54 +    public boolean isConvertibleFrom(Wrapper source) {
   34.55 +        if (this == source)  return true;
   34.56 +        if (this.compareTo(source) < 0) {
   34.57 +            // At best, this is a narrowing conversion.
   34.58 +            return false;
   34.59 +        }
   34.60 +        if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) {
   34.61 +            assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT);
   34.62 +            return false;
   34.63 +        }
   34.64 +        return true;
   34.65 +    }
   34.66 +
   34.67      /** Produce a zero value for the given wrapper type.
   34.68       *  This will be a numeric zero for a number or character,
   34.69       *  false for a boolean, and null for a reference or void.
   34.70 @@ -122,10 +149,10 @@
   34.71      public Object zero() { return zero; }
   34.72  
   34.73      /** Produce a zero value for the given wrapper type T.
   34.74 -     *  The optinoal argument must a type compatible with this wrapper.
   34.75 +     *  The optional argument must a type compatible with this wrapper.
   34.76       *  Equivalent to {@code this.cast(this.zero(), type)}.
   34.77       */
   34.78 -    public <T> T zero(Class<T> type) { return cast(zero, type); }
   34.79 +    public <T> T zero(Class<T> type) { return convert(zero, type); }
   34.80  
   34.81  //    /** Produce a wrapper for the given wrapper or primitive type. */
   34.82  //    public static Wrapper valueOf(Class<?> type) {
   34.83 @@ -264,7 +291,11 @@
   34.84                     exampleType.isInterface()) {
   34.85              return forceType(wrapperType, exampleType);
   34.86          }
   34.87 -        throw new ClassCastException(exampleType + " not <:" + wrapperType);
   34.88 +        throw newClassCastException(exampleType, primitiveType);
   34.89 +    }
   34.90 +
   34.91 +    private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
   34.92 +        return new ClassCastException(actual + " is not compatible with " + expected);
   34.93      }
   34.94  
   34.95      /** If {@code type} is a primitive type, return the corresponding
   34.96 @@ -325,17 +356,55 @@
   34.97  //    }
   34.98  
   34.99      /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
  34.100 +     *  The given target type must be this wrapper's primitive or wrapper type.
  34.101 +     *  If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
  34.102       *  Performs standard primitive conversions, including truncation and float conversions.
  34.103       *  The given type must be compatible with this wrapper.  That is, it must either
  34.104       *  be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
  34.105       *  it must be the wrapper's primitive type.
  34.106 +     *  Primitive conversions are only performed if the given type is itself a primitive.
  34.107       *  @throws ClassCastException if the given type is not compatible with this wrapper
  34.108       */
  34.109      public <T> T cast(Object x, Class<T> type) {
  34.110 +        return convert(x, type, true);
  34.111 +    }
  34.112 +
  34.113 +    /** Convert a wrapped value to the given type.
  34.114 +     *  The given target type must be this wrapper's primitive or wrapper type.
  34.115 +     *  This is equivalent to {@link #cast}, except that it refuses to perform
  34.116 +     *  narrowing primitive conversions.
  34.117 +     */
  34.118 +    public <T> T convert(Object x, Class<T> type) {
  34.119 +        return convert(x, type, false);
  34.120 +    }
  34.121 +
  34.122 +    private <T> T convert(Object x, Class<T> type, boolean isCast) {
  34.123 +        if (this == OBJECT) {
  34.124 +            // If the target wrapper is OBJECT, just do a reference cast.
  34.125 +            // If the target type is an interface, perform no runtime check.
  34.126 +            // (This loophole is safe, and is allowed by the JVM verifier.)
  34.127 +            // If the target type is a primitive, change it to a wrapper.
  34.128 +            @SuppressWarnings("unchecked")
  34.129 +            T result = (T) x;  // unchecked warning is expected here
  34.130 +            return result;
  34.131 +        }
  34.132          Class<T> wtype = wrapperType(type);
  34.133 -        if (wtype.isInstance(x))
  34.134 -            return wtype.cast(x);
  34.135 -        return wtype.cast(wrap(x));
  34.136 +        if (wtype.isInstance(x)) {
  34.137 +            @SuppressWarnings("unchecked")
  34.138 +            T result = (T) x;  // unchecked warning is expected here
  34.139 +            return result;
  34.140 +        }
  34.141 +        Class<?> sourceType = x.getClass();  // throw NPE if x is null
  34.142 +        if (!isCast) {
  34.143 +            Wrapper source = findWrapperType(sourceType);
  34.144 +            if (source == null || !this.isConvertibleFrom(source)) {
  34.145 +                throw newClassCastException(wtype, sourceType);
  34.146 +            }
  34.147 +        }
  34.148 +        @SuppressWarnings("unchecked")
  34.149 +        T result = (T) wrap(x);  // unchecked warning is expected here
  34.150 +        assert result.getClass() == wtype;
  34.151 +        return result;
  34.152      }
  34.153  
  34.154      /** Cast a reference type to another reference type.
    35.1 --- a/test/java/dyn/ClassValueTest.java	Tue Dec 21 15:27:55 2010 -0800
    35.2 +++ b/test/java/dyn/ClassValueTest.java	Tue Dec 21 18:45:45 2010 -0800
    35.3 @@ -53,12 +53,13 @@
    35.4          return "CV1:" + type.getName();
    35.5      }
    35.6      static int countForCV1;
    35.7 -    static final ClassValue<String> CV1 = new ClassValue<String>() {
    35.8 +    static final ClassValue<String> CV1 = new CV1();
    35.9 +    private static class CV1 extends ClassValue<String> {
   35.10          protected String computeValue(Class<?> type) {
   35.11              countForCV1++;
   35.12              return nameForCV1(type);
   35.13          }
   35.14 -    };
   35.15 +    }
   35.16  
   35.17      static final Class[] CLASSES = {
   35.18          String.class,
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/test/java/dyn/InvokeDynamicPrintArgs.java	Tue Dec 21 18:45:45 2010 -0800
    36.3 @@ -0,0 +1,172 @@
    36.4 +/*
    36.5 + * Copyright (c) 2010, Oracle and/or its affiliates. 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.
   36.11 + *
   36.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.15 + * version 2 for more details (a copy is included in the LICENSE file that
   36.16 + * accompanied this code).
   36.17 + *
   36.18 + * You should have received a copy of the GNU General Public License version
   36.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.21 + *
   36.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.23 + * or visit www.oracle.com if you need additional information or have any
   36.24 + * questions.
   36.25 + */
   36.26 +
   36.27 +/* @test
   36.28 + * @summary smoke test for invokedynamic instructions
   36.29 + * @library indify
   36.30 + * @compile InvokeDynamicPrintArgs.java
   36.31 + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic
   36.32 + *      indify.Indify
   36.33 + *      --verify-specifier-count=3 --transitionalJSR292=false
   36.34 + *      --expand-properties --classpath ${test.classes}
   36.35 + *      --java InvokeDynamicPrintArgs --check-output
   36.36 + */
   36.37 +
   36.38 +import java.util.*;
   36.39 +import java.io.*;
   36.40 +
   36.41 +import java.dyn.*;
   36.42 +import static java.dyn.MethodHandles.*;
   36.43 +import static java.dyn.MethodType.*;
   36.44 +
   36.45 +public class InvokeDynamicPrintArgs {
   36.46 +    public static void main(String... av) throws Throwable {
   36.47 +        if (av.length > 0)  openBuf();  // --check-output mode
   36.48 +        System.out.println("Printing some argument lists, starting with a empty one:");
   36.49 +        INDY_nothing().invokeExact();                 // BSM specifier #0 = {bsm}
   36.50 +        INDY_bar().invokeExact("bar arg", 1);         // BSM specifier #1 = {bsm2, Void.class, "void type"}
   36.51 +        INDY_bar2().invokeExact("bar2 arg", 222);     // BSM specifier #1 = (same)
   36.52 +        INDY_baz().invokeExact("baz arg", 2, 3.14);   // BSM specifier #2 = {bsm2, 1234.5}
   36.53 +        INDY_foo().invokeExact("foo arg");            // BSM specifier #0 = (same)
   36.54 +        // Hence, BSM specifier count should be 3.  See "--verify-specifier-count=3" above.
   36.55 +        System.out.println("Done printing argument lists.");
   36.56 +        closeBuf();
   36.57 +    }
   36.58 +
   36.59 +    private static PrintStream oldOut;
   36.60 +    private static ByteArrayOutputStream buf;
   36.61 +    private static void openBuf() {
   36.62 +        oldOut = System.out;
   36.63 +        buf = new ByteArrayOutputStream();
   36.64 +        System.setOut(new PrintStream(buf));
   36.65 +    }
   36.66 +    private static void closeBuf() {
   36.67 +        if (buf == null)  return;
   36.68 +        System.out.flush();
   36.69 +        System.setOut(oldOut);
   36.70 +        String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
   36.71 +        for (String line : haveLines)  System.out.println(line);
   36.72 +        Iterator<String> iter = Arrays.asList(haveLines).iterator();
   36.73 +        for (String want : EXPECT_OUTPUT) {
   36.74 +            String have = iter.hasNext() ? iter.next() : "[EOF]";
   36.75 +            if (want.equals(have))  continue;
   36.76 +            System.err.println("want line: "+want);
   36.77 +            System.err.println("have line: "+have);
   36.78 +            throw new AssertionError("unexpected output: "+have);
   36.79 +        }
   36.80 +        if (iter.hasNext())
   36.81 +            throw new AssertionError("unexpected output: "+iter.next());
   36.82 +    }
   36.83 +    private static final String[] EXPECT_OUTPUT = {
   36.84 +        "Printing some argument lists, starting with a empty one:",
   36.85 +        "[InvokeDynamicPrintArgs, nothing, ()void][]",
   36.86 +        "[InvokeDynamicPrintArgs, bar, (java.lang.String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
   36.87 +        "[InvokeDynamicPrintArgs, bar2, (java.lang.String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
   36.88 +        "[InvokeDynamicPrintArgs, baz, (java.lang.String,int,double)void, 1234.5][baz arg, 2, 3.14]",
   36.89 +        "[InvokeDynamicPrintArgs, foo, (java.lang.String)void][foo arg]",
   36.90 +        "Done printing argument lists."
   36.91 +    };
   36.92 +
   36.93 +    private static void printArgs(Object bsmInfo, Object... args) {
   36.94 +        System.out.println(bsmInfo+Arrays.deepToString(args));
   36.95 +    }
   36.96 +    private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
   36.97 +        shouldNotCallThis();
   36.98 +        return lookup().findStatic(lookup().lookupClass(),
   36.99 +                                   "printArgs", methodType(void.class, Object.class, Object[].class));
  36.100 +    }
  36.101 +
  36.102 +    private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
  36.103 +        // ignore caller and name, but match the type:
  36.104 +        Object bsmInfo = Arrays.asList(caller, name, type);
  36.105 +        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
  36.106 +    }
  36.107 +    private static MethodType MT_bsm() {
  36.108 +        shouldNotCallThis();
  36.109 +        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
  36.110 +    }
  36.111 +    private static MethodHandle MH_bsm() throws ReflectiveOperationException {
  36.112 +        shouldNotCallThis();
  36.113 +        return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
  36.114 +    }
  36.115 +
  36.116 +    private static CallSite bsm2(Lookup caller, String name, MethodType type, Object arg) throws ReflectiveOperationException {
  36.117 +        // ignore caller and name, but match the type:
  36.118 +        List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type));
  36.119 +        if (arg instanceof Object[])
  36.120 +            bsmInfo.addAll(Arrays.asList((Object[])arg));
  36.121 +        else
  36.122 +            bsmInfo.add(arg);
  36.123 +        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
  36.124 +    }
  36.125 +    private static MethodType MT_bsm2() {
  36.126 +        shouldNotCallThis();
  36.127 +        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object.class);
  36.128 +    }
  36.129 +    private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
  36.130 +        shouldNotCallThis();
  36.131 +        return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
  36.132 +    }
  36.133 +
  36.134 +    private static MethodHandle INDY_nothing() throws Throwable {
  36.135 +        shouldNotCallThis();
  36.136 +        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
  36.137 +                                                  "nothing", methodType(void.class)
  36.138 +                                                  )).dynamicInvoker();
  36.139 +    }
  36.140 +    private static MethodHandle INDY_foo() throws Throwable {
  36.141 +        shouldNotCallThis();
  36.142 +        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
  36.143 +                                                  "foo", methodType(void.class, String.class)
  36.144 +                                                  )).dynamicInvoker();
  36.145 +    }
  36.146 +    private static MethodHandle INDY_bar() throws Throwable {
  36.147 +        shouldNotCallThis();
  36.148 +        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
  36.149 +                                                  "bar", methodType(void.class, String.class, int.class)
  36.150 +                                                  , new Object[] { Void.class, "void type!",
  36.151 +                                                                   1, 234.5F, 67.5, (long)89 }
  36.152 +                                                  )).dynamicInvoker();
  36.153 +    }
  36.154 +    private static MethodHandle INDY_bar2() throws Throwable {
  36.155 +        shouldNotCallThis();
  36.156 +        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
  36.157 +                                                  "bar2", methodType(void.class, String.class, int.class)
  36.158 +                                                  , new Object[] { Void.class, "void type!",
  36.159 +                                                                   1, 234.5F, 67.5, (long)89 }
  36.160 +                                                  )).dynamicInvoker();
  36.161 +    }
  36.162 +    private static MethodHandle INDY_baz() throws Throwable {
  36.163 +        shouldNotCallThis();
  36.164 +        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
  36.165 +                                                  "baz", methodType(void.class, String.class, int.class, double.class)
  36.166 +                                                  , 1234.5
  36.167 +                                                  )).dynamicInvoker();
  36.168 +    }
  36.169 +
  36.170 +    private static void shouldNotCallThis() {
  36.171 +        // if this gets called, the transformation has not taken place
  36.172 +        if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null)  return;
  36.173 +        throw new AssertionError("this code should be statically transformed away by Indify");
  36.174 +    }
  36.175 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/test/java/dyn/InvokeGenericTest.java	Tue Dec 21 18:45:45 2010 -0800
    37.3 @@ -0,0 +1,484 @@
    37.4 +/*
    37.5 + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   37.11 + * particular file as subject to the "Classpath" exception as provided
   37.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   37.25 + * or visit www.oracle.com if you need additional information or have any
   37.26 + * questions.
   37.27 + */
   37.28 +
   37.29 +/* @test
   37.30 + * @summary unit tests for java.dyn.MethodHandle.invokeGeneric
   37.31 + * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
   37.32 + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest
   37.33 + */
   37.34 +
   37.35 +package test.java.dyn;
   37.36 +
   37.37 +import java.dyn.*;
   37.38 +import static java.dyn.MethodHandles.*;
   37.39 +import static java.dyn.MethodType.*;
   37.40 +import java.lang.reflect.*;
   37.41 +import java.util.*;
   37.42 +import org.junit.*;
   37.43 +import static org.junit.Assert.*;
   37.44 +import static org.junit.Assume.*;
   37.45 +
   37.46 +
   37.47 +/**
   37.48 + *
   37.49 + * @author jrose
   37.50 + */
   37.51 +public class InvokeGenericTest {
   37.52 +    // How much output?
   37.53 +    static int verbosity = 0;
   37.54 +    static {
   37.55 +        String vstr = System.getProperty("test.java.dyn.InvokeGenericTest.verbosity");
   37.56 +        if (vstr != null)  verbosity = Integer.parseInt(vstr);
   37.57 +    }
   37.58 +
   37.59 +    @Test
   37.60 +    public void testFirst() throws Throwable {
   37.61 +        verbosity += 9; try {
   37.62 +            // left blank for debugging
   37.63 +        } finally { printCounts(); verbosity -= 9; }
   37.64 +    }
   37.65 +
   37.66 +    public InvokeGenericTest() {
   37.67 +    }
   37.68 +
   37.69 +    @Before
   37.70 +    public void checkImplementedPlatform() {
   37.71 +        boolean platformOK = false;
   37.72 +        Properties properties = System.getProperties();
   37.73 +        String vers = properties.getProperty("java.vm.version");
   37.74 +        String name = properties.getProperty("java.vm.name");
   37.75 +        String arch = properties.getProperty("os.arch");
   37.76 +        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
   37.77 +             arch.equals("sparc") || arch.equals("sparcv9")) &&
   37.78 +            (name.contains("Client") || name.contains("Server"))
   37.79 +            ) {
   37.80 +            platformOK = true;
   37.81 +        } else {
   37.82 +            System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
   37.83 +        }
   37.84 +        assumeTrue(platformOK);
   37.85 +    }
   37.86 +
   37.87 +    String testName;
   37.88 +    static int allPosTests, allNegTests;
   37.89 +    int posTests, negTests;
   37.90 +    @After
   37.91 +    public void printCounts() {
   37.92 +        if (verbosity >= 2 && (posTests | negTests) != 0) {
   37.93 +            System.out.println();
   37.94 +            if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
   37.95 +            if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
   37.96 +            allPosTests += posTests;
   37.97 +            allNegTests += negTests;
   37.98 +            posTests = negTests = 0;
   37.99 +        }
  37.100 +    }
  37.101 +    void countTest(boolean positive) {
  37.102 +        if (positive) ++posTests;
  37.103 +        else          ++negTests;
  37.104 +    }
  37.105 +    void countTest() { countTest(true); }
  37.106 +    void startTest(String name) {
  37.107 +        if (testName != null)  printCounts();
  37.108 +        if (verbosity >= 1)
  37.109 +            System.out.println(name);
  37.110 +        posTests = negTests = 0;
  37.111 +        testName = name;
  37.112 +    }
  37.113 +
  37.114 +    @BeforeClass
  37.115 +    public static void setUpClass() throws Exception {
  37.116 +        calledLog.clear();
  37.117 +        calledLog.add(null);
  37.118 +        nextArgVal = INITIAL_ARG_VAL;
  37.119 +    }
  37.120 +
  37.121 +    @AfterClass
  37.122 +    public static void tearDownClass() throws Exception {
  37.123 +        int posTests = allPosTests, negTests = allNegTests;
  37.124 +        if (verbosity >= 2 && (posTests | negTests) != 0) {
  37.125 +            System.out.println();
  37.126 +            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
  37.127 +            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
  37.128 +        }
  37.129 +    }
  37.130 +
  37.131 +    static List<Object> calledLog = new ArrayList<Object>();
  37.132 +    static Object logEntry(String name, Object... args) {
  37.133 +        return Arrays.asList(name, Arrays.asList(args));
  37.134 +    }
  37.135 +    static Object called(String name, Object... args) {
  37.136 +        Object entry = logEntry(name, args);
  37.137 +        calledLog.add(entry);
  37.138 +        return entry;
  37.139 +    }
  37.140 +    static void assertCalled(String name, Object... args) {
  37.141 +        Object expected = logEntry(name, args);
  37.142 +        Object actual   = calledLog.get(calledLog.size() - 1);
  37.143 +        if (expected.equals(actual) && verbosity < 9)  return;
  37.144 +        System.out.println("assertCalled "+name+":");
  37.145 +        System.out.println("expected:   "+expected);
  37.146 +        System.out.println("actual:     "+actual);
  37.147 +        System.out.println("ex. types:  "+getClasses(expected));
  37.148 +        System.out.println("act. types: "+getClasses(actual));
  37.149 +        assertEquals("previous method call", expected, actual);
  37.150 +    }
  37.151 +    static void printCalled(MethodHandle target, String name, Object... args) {
  37.152 +        if (verbosity >= 3)
  37.153 +            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
  37.154 +    }
  37.155 +
  37.156 +    static Object castToWrapper(Object value, Class<?> dst) {
  37.157 +        Object wrap = null;
  37.158 +        if (value instanceof Number)
  37.159 +            wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
  37.160 +        if (value instanceof Character)
  37.161 +            wrap = castToWrapperOrNull((char)(Character)value, dst);
  37.162 +        if (wrap != null)  return wrap;
  37.163 +        return dst.cast(value);
  37.164 +    }
  37.165 +
  37.166 +    static Object castToWrapperOrNull(long value, Class<?> dst) {
  37.167 +        if (dst == int.class || dst == Integer.class)
  37.168 +            return (int)(value);
  37.169 +        if (dst == long.class || dst == Long.class)
  37.170 +            return (long)(value);
  37.171 +        if (dst == char.class || dst == Character.class)
  37.172 +            return (char)(value);
  37.173 +        if (dst == short.class || dst == Short.class)
  37.174 +            return (short)(value);
  37.175 +        if (dst == float.class || dst == Float.class)
  37.176 +            return (float)(value);
  37.177 +        if (dst == double.class || dst == Double.class)
  37.178 +            return (double)(value);
  37.179 +        if (dst == byte.class || dst == Byte.class)
  37.180 +            return (byte)(value);
  37.181 +        if (dst == boolean.class || dst == boolean.class)
  37.182 +            return ((value % 29) & 1) == 0;
  37.183 +        return null;
  37.184 +    }
  37.185 +
  37.186 +    static final int ONE_MILLION = (1000*1000),  // first int value
  37.187 +                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
  37.188 +                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
  37.189 +    static long nextArgVal;
  37.190 +    static long nextArg(boolean moreBits) {
  37.191 +        long val = nextArgVal++;
  37.192 +        long sign = -(val & 1); // alternate signs
  37.193 +        val >>= 1;
  37.194 +        if (moreBits)
  37.195 +            // Guarantee some bits in the high word.
  37.196 +            // In any case keep the decimal representation simple-looking,
  37.197 +            // with lots of zeroes, so as not to make the printed decimal
  37.198 +            // strings unnecessarily noisy.
  37.199 +            val += (val % ONE_MILLION) * TEN_BILLION;
  37.200 +        return val ^ sign;
  37.201 +    }
  37.202 +    static int nextArg() {
  37.203 +        // Produce a 32-bit result something like ONE_MILLION+(smallint).
  37.204 +        // Example: 1_000_042.
  37.205 +        return (int) nextArg(false);
  37.206 +    }
  37.207 +    static long nextArg(Class<?> kind) {
  37.208 +        if (kind == long.class   || kind == Long.class ||
  37.209 +            kind == double.class || kind == Double.class)
  37.210 +            // produce a 64-bit result something like
  37.211 +            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
  37.212 +            // Example: 10_000_420_001_000_042.
  37.213 +            return nextArg(true);
  37.214 +        return (long) nextArg();
  37.215 +    }
  37.216 +
  37.217 +    static Object randomArg(Class<?> param) {
  37.218 +        Object wrap = castToWrapperOrNull(nextArg(param), param);
  37.219 +        if (wrap != null) {
  37.220 +            return wrap;
  37.221 +        }
  37.222 +//        import sun.dyn.util.Wrapper;
  37.223 +//        Wrapper wrap = Wrapper.forBasicType(dst);
  37.224 +//        if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
  37.225 +//            wrap = Wrapper.forWrapperType(dst);
  37.226 +//        if (wrap != Wrapper.OBJECT)
  37.227 +//            return wrap.wrap(nextArg++);
  37.228 +        if (param.isInterface()) {
  37.229 +            for (Class<?> c : param.getClasses()) {
  37.230 +                if (param.isAssignableFrom(c) && !c.isInterface())
  37.231 +                    { param = c; break; }
  37.232 +            }
  37.233 +        }
  37.234 +        if (param.isInterface() || param.isAssignableFrom(String.class))
  37.235 +            return "#"+nextArg();
  37.236 +        else
  37.237 +            try {
  37.238 +                return param.newInstance();
  37.239 +            } catch (InstantiationException ex) {
  37.240 +            } catch (IllegalAccessException ex) {
  37.241 +            }
  37.242 +        return null;  // random class not Object, String, Integer, etc.
  37.243 +    }
  37.244 +    static Object[] randomArgs(Class<?>... params) {
  37.245 +        Object[] args = new Object[params.length];
  37.246 +        for (int i = 0; i < args.length; i++)
  37.247 +            args[i] = randomArg(params[i]);
  37.248 +        return args;
  37.249 +    }
  37.250 +    static Object[] randomArgs(int nargs, Class<?> param) {
  37.251 +        Object[] args = new Object[nargs];
  37.252 +        for (int i = 0; i < args.length; i++)
  37.253 +            args[i] = randomArg(param);
  37.254 +        return args;
  37.255 +    }
  37.256 +
  37.257 +    static final Object ANON_OBJ = new Object();
  37.258 +    static Object zeroArg(Class<?> param) {
  37.259 +        Object x = castToWrapperOrNull(0L, param);
  37.260 +        if (x != null)  return x;
  37.261 +        if (param.isInterface() || param.isAssignableFrom(String.class))  return "\"\"";
  37.262 +        if (param == Object.class)  return ANON_OBJ;
  37.263 +        if (param.getComponentType() != null)  return Array.newInstance(param.getComponentType(), 0);
  37.264 +        return null;
  37.265 +    }
  37.266 +    static Object[] zeroArgs(Class<?>... params) {
  37.267 +        Object[] args = new Object[params.length];
  37.268 +        for (int i = 0; i < args.length; i++)
  37.269 +            args[i] = zeroArg(params[i]);
  37.270 +        return args;
  37.271 +    }
  37.272 +    static Object[] zeroArgs(List<Class<?>> params) {
  37.273 +        return zeroArgs(params.toArray(new Class<?>[0]));
  37.274 +    }
  37.275 +
  37.276 +    static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
  37.277 +        return Arrays.copyOf(a, a.length, atype);
  37.278 +    }
  37.279 +    static <T> T[] cat(T[] a, T... b) {
  37.280 +        int alen = a.length, blen = b.length;
  37.281 +        if (blen == 0)  return a;
  37.282 +        T[] c = Arrays.copyOf(a, alen + blen);
  37.283 +        System.arraycopy(b, 0, c, alen, blen);
  37.284 +        return c;
  37.285 +    }
  37.286 +    static Integer[] boxAll(int... vx) {
  37.287 +        Integer[] res = new Integer[vx.length];
  37.288 +        for (int i = 0; i < res.length; i++) {
  37.289 +            res[i] = vx[i];
  37.290 +        }
  37.291 +        return res;
  37.292 +    }
  37.293 +    static Object getClasses(Object x) {
  37.294 +        if (x == null)  return x;
  37.295 +        if (x instanceof String)  return x;  // keep the name
  37.296 +        if (x instanceof List) {
  37.297 +            // recursively report classes of the list elements
  37.298 +            Object[] xa = ((List)x).toArray();
  37.299 +            for (int i = 0; i < xa.length; i++)
  37.300 +                xa[i] = getClasses(xa[i]);
  37.301 +            return Arrays.asList(xa);
  37.302 +        }
  37.303 +        return x.getClass().getSimpleName();
  37.304 +    }
  37.305 +
  37.306 +    static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
  37.307 +        return changeArgTypes(target, 0, 999, argType);
  37.308 +    }
  37.309 +    static MethodHandle changeArgTypes(MethodHandle target,
  37.310 +            int beg, int end, Class<?> argType) {
  37.311 +        MethodType targetType = target.type();
  37.312 +        end = Math.min(end, targetType.parameterCount());
  37.313 +        ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
  37.314 +        Collections.fill(argTypes.subList(beg, end), argType);
  37.315 +        MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
  37.316 +        return MethodHandles.convertArguments(target, ttype2);
  37.317 +    }
  37.318 +
  37.319 +    // This lookup is good for all members in and under InvokeGenericTest.
  37.320 +    static final Lookup LOOKUP = MethodHandles.lookup();
  37.321 +
  37.322 +    Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<List<Class<?>>, MethodHandle>();
  37.323 +    MethodHandle callable(List<Class<?>> params) {
  37.324 +        MethodHandle mh = CALLABLES.get(params);
  37.325 +        if (mh == null) {
  37.326 +            mh = collectArguments(collector_MH, methodType(Object.class, params));
  37.327 +            CALLABLES.put(params, mh);
  37.328 +        }
  37.329 +        return mh;
  37.330 +    }
  37.331 +    MethodHandle callable(Class<?>... params) {
  37.332 +        return callable(Arrays.asList(params));
  37.333 +    }
  37.334 +    private static Object collector(Object... args) {
  37.335 +        return Arrays.asList(args);
  37.336 +    }
  37.337 +    private static final MethodHandle collector_MH;
  37.338 +    static {
  37.339 +        try {
  37.340 +            collector_MH
  37.341 +                = LOOKUP.findStatic(LOOKUP.lookupClass(),
  37.342 +                                    "collector",
  37.343 +                                    methodType(Object.class, Object[].class));
  37.344 +        } catch (NoAccessException ex) {
  37.345 +            throw new RuntimeException(ex);
  37.346 +        }
  37.347 +    }
  37.348 +
  37.349 +    @Test
  37.350 +    public void testSimple() throws Throwable {
  37.351 +        startTest("testSimple");
  37.352 +        countTest();
  37.353 +        String[] args = { "one", "two" };
  37.354 +        MethodHandle mh = callable(Object.class, String.class);
  37.355 +        Object res; List resl;
  37.356 +        res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
  37.357 +        //System.out.println(res);
  37.358 +        assertEquals(Arrays.asList(args), res);
  37.359 +    }
  37.360 +
  37.361 +    @Test
  37.362 +    public void testWrongArgumentCount() throws Throwable {
  37.363 +        startTest("testWrongArgumentCount");
  37.364 +        for (int i = 0; i <= 10; i++) {
  37.365 +            testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
  37.366 +            if (i <= 4) {
  37.367 +                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
  37.368 +                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
  37.369 +            }
  37.370 +        }
  37.371 +    }
  37.372 +    public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
  37.373 +        int max = params.size();
  37.374 +        for (int i = 0; i < max; i++) {
  37.375 +            List<Class<?>> params2 = params.subList(0, i);
  37.376 +            for (int k = 0; k <= 2; k++) {
  37.377 +                if (k == 1)  params  = methodType(Object.class,  params).generic().parameterList();
  37.378 +                if (k == 2)  params2 = methodType(Object.class, params2).generic().parameterList();
  37.379 +                testWrongArgumentCount(params, params2);
  37.380 +                testWrongArgumentCount(params2, params);
  37.381 +            }
  37.382 +        }
  37.383 +    }
  37.384 +    public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
  37.385 +        countTest(false);
  37.386 +        if (expect.equals(observe))
  37.387 +            assert(false);
  37.388 +        MethodHandle target = callable(expect);
  37.389 +        Object[] args = zeroArgs(observe);
  37.390 +        Object junk;
  37.391 +        try {
  37.392 +            switch (args.length) {
  37.393 +            case 0:
  37.394 +                junk = target.invokeGeneric(); break;
  37.395 +            case 1:
  37.396 +                junk = target.invokeGeneric(args[0]); break;
  37.397 +            case 2:
  37.398 +                junk = target.invokeGeneric(args[0], args[1]); break;
  37.399 +            case 3:
  37.400 +                junk = target.invokeGeneric(args[0], args[1], args[2]); break;
  37.401 +            case 4:
  37.402 +                junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break;
  37.403 +            default:
  37.404 +                junk = target.invokeWithArguments(args); break;
  37.405 +            }
  37.406 +        } catch (WrongMethodTypeException ex) {
  37.407 +            return;
  37.408 +        } catch (Exception ex) {
  37.409 +            throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex);
  37.410 +        }
  37.411 +        throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args));
  37.412 +    }
  37.413 +
  37.414 +    /** Make a list of all combinations of the given types, with the given arities.
  37.415 +     *  A void return type is possible iff the first type is void.class.
  37.416 +     */
  37.417 +    static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
  37.418 +        ArrayList<MethodType> result = new ArrayList<MethodType>();
  37.419 +        if (types.length > 0) {
  37.420 +            ArrayList<MethodType> argcTypes = new ArrayList<MethodType>();
  37.421 +            // build arity-zero types first
  37.422 +            for (Class<?> rtype : types) {
  37.423 +                argcTypes.add(MethodType.methodType(rtype));
  37.424 +            }
  37.425 +            if (types[0] == void.class)
  37.426 +                // void is not an argument type
  37.427 +                types = Arrays.copyOfRange(types, 1, types.length);
  37.428 +            for (int argc = 0; argc <= maxargc; argc++) {
  37.429 +                if (argc >= minargc)
  37.430 +                    result.addAll(argcTypes);
  37.431 +                if (argc >= maxargc)
  37.432 +                    break;
  37.433 +                ArrayList<MethodType> prevTypes = argcTypes;
  37.434 +                argcTypes = new ArrayList<MethodType>();
  37.435 +                for (MethodType prevType : prevTypes) {
  37.436 +                    for (Class<?> ptype : types) {
  37.437 +                        argcTypes.add(prevType.insertParameterTypes(argc, ptype));
  37.438 +                    }
  37.439 +                }
  37.440 +            }
  37.441 +        }
  37.442 +        return Collections.unmodifiableList(result);
  37.443 +    }
  37.444 +    static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
  37.445 +        return allMethodTypes(argc, argc, types);
  37.446 +    }
  37.447 +
  37.448 +    interface RandomInterface { }
  37.449 +
  37.450 +    MethodHandle toString_MH;
  37.451 +
  37.452 +    @Test
  37.453 +    public void testReferenceConversions() throws Throwable {
  37.454 +        startTest("testReferenceConversions");
  37.455 +        toString_MH = LOOKUP.
  37.456 +            findVirtual(Object.class, "toString", MethodType.methodType(String.class));
  37.457 +        String[] args = { "one", "two" };
  37.458 +        for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
  37.459 +            testReferenceConversions(type, args);
  37.460 +        }
  37.461 +    }
  37.462 +    public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
  37.463 +        countTest();
  37.464 +        if (verbosity > 3)  System.out.println("target type: "+type);
  37.465 +        MethodHandle mh = callable(type.parameterList());
  37.466 +        MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
  37.467 +        mh = MethodHandles.foldArguments(tsdrop, mh);
  37.468 +        mh = mh.asType(type);
  37.469 +        Object res = mh.invokeGeneric((String)args[0], (Object)args[1]);
  37.470 +        //System.out.println(res);
  37.471 +        assertEquals(Arrays.asList(args).toString(), res);
  37.472 +    }
  37.473 +
  37.474 +
  37.475 +    @Test @Ignore("known failure pending 6939861")
  37.476 +    public void testBoxConversions() throws Throwable {
  37.477 +        startTest("testBoxConversions");
  37.478 +        countTest();
  37.479 +        Integer[] args = { 1, 2 };
  37.480 +        MethodHandle mh = callable(Object.class, int.class);
  37.481 +        Object res; List resl;
  37.482 +        res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]);
  37.483 +        //System.out.println(res);
  37.484 +        assertEquals(Arrays.asList(args), res);
  37.485 +    }
  37.486 +
  37.487 +}
    38.1 --- a/test/java/dyn/JavaDocExamples.java	Tue Dec 21 15:27:55 2010 -0800
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,128 +0,0 @@
    38.4 -/*
    38.5 - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   38.11 - * particular file as subject to the "Classpath" exception as provided
   38.12 - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   38.25 - * or visit www.oracle.com if you need additional information or have any
   38.26 - * questions.
   38.27 - */
   38.28 -
   38.29 -/* @test
   38.30 - * @summary example code used in javadoc for java.dyn API
   38.31 - * @compile -XDallowTransitionalJSR292=no JavaDocExamples.java
   38.32 - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples
   38.33 - */
   38.34 -
   38.35 -/*
   38.36 ----- To run outside jtreg:
   38.37 -$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
   38.38 -   $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples.java
   38.39 -$ $JAVA7X_HOME/bin/java   -cp $JUNIT4_JAR:/tmp/Classes \
   38.40 -   -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
   38.41 -   -Dtest.java.dyn.JavaDocExamples.verbosity=1 \
   38.42 -     test.java.dyn.JavaDocExamples
   38.43 -----
   38.44 -*/
   38.45 -
   38.46 -package test.java.dyn;
   38.47 -
   38.48 -import java.dyn.*;
   38.49 -import static java.dyn.MethodHandles.*;
   38.50 -import static java.dyn.MethodType.*;
   38.51 -
   38.52 -import java.lang.reflect.*;
   38.53 -import java.util.*;
   38.54 -
   38.55 -import org.junit.*;
   38.56 -import static org.junit.Assert.*;
   38.57 -import static org.junit.Assume.*;
   38.58 -
   38.59 -
   38.60 -/**
   38.61 - * @author jrose
   38.62 - */
   38.63 -public class JavaDocExamples {
   38.64 -    /** Wrapper for running the JUnit tests in this module.
   38.65 -     *  Put JUnit on the classpath!
   38.66 -     */
   38.67 -    public static void main(String... ignore) {
   38.68 -        org.junit.runner.JUnitCore.runClasses(JavaDocExamples.class);
   38.69 -    }
   38.70 -    // How much output?
   38.71 -    static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamples.verbosity", 0);
   38.72 -
   38.73 -{}
   38.74 -static final private Lookup LOOKUP = lookup();
   38.75 -// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
   38.76 -//     "concat", methodType(String.class, String.class));
   38.77 -// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
   38.78 -//     "hashCode", methodType(int.class));
   38.79 -
   38.80 -// form required if NoAccessException is intercepted:
   38.81 -static final private MethodHandle CONCAT_2, HASHCODE_2;
   38.82 -static {
   38.83 -  try {
   38.84 -    CONCAT_2 = LOOKUP.findVirtual(String.class,
   38.85 -      "concat", methodType(String.class, String.class));
   38.86 -    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
   38.87 -      "hashCode", methodType(int.class));
   38.88 -   } catch (NoAccessException ex) {
   38.89 -     throw new RuntimeException(ex);
   38.90 -   }
   38.91 -}
   38.92 -{}
   38.93 -
   38.94 -    @Test public void testFindVirtual() throws Throwable {
   38.95 -{}
   38.96 -MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
   38.97 -  "concat", methodType(String.class, String.class));
   38.98 -MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
   38.99 -  "hashCode", methodType(int.class));
  38.100 -//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
  38.101 -assertEquals("xy", (String) CONCAT_2.<String>invokeExact("x", "y"));
  38.102 -assertEquals("xy", (String) CONCAT_3.<String>invokeExact("x", "y"));
  38.103 -//assertEquals("xy".hashCode(), (int) HASHCODE_1.<int>invokeExact((Object)"xy"));
  38.104 -assertEquals("xy".hashCode(), (int) HASHCODE_2.<int>invokeExact((Object)"xy"));
  38.105 -assertEquals("xy".hashCode(), (int) HASHCODE_3.<int>invokeExact((Object)"xy"));
  38.106 -{}
  38.107 -    }
  38.108 -    @Test public void testDropArguments() throws Throwable {
  38.109 -        {{
  38.110 -{} /// JAVADOC
  38.111 -MethodHandle cat = lookup().findVirtual(String.class,
  38.112 -  "concat", methodType(String.class, String.class));
  38.113 -cat = cat.asType(methodType(Object.class, String.class, String.class)); /*(String)*/
  38.114 -assertEquals("xy", /*(String)*/ cat.invokeExact("x", "y"));
  38.115 -MethodHandle d0 = dropArguments(cat, 0, String.class);
  38.116 -assertEquals("yz", /*(String)*/ d0.invokeExact("x", "y", "z"));
  38.117 -MethodHandle d1 = dropArguments(cat, 1, String.class);
  38.118 -assertEquals("xz", /*(String)*/ d1.invokeExact("x", "y", "z"));
  38.119 -MethodHandle d2 = dropArguments(cat, 2, String.class);
  38.120 -assertEquals("xy", /*(String)*/ d2.invokeExact("x", "y", "z"));
  38.121 -MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
  38.122 -assertEquals("xz", /*(String)*/ d12.invokeExact("x", 12, true, "z"));
  38.123 -            }}
  38.124 -    }
  38.125 -
  38.126 -    static void assertEquals(Object exp, Object act) {
  38.127 -        if (verbosity > 0)
  38.128 -            System.out.println("result: "+act);
  38.129 -        Assert.assertEquals(exp, act);
  38.130 -    }
  38.131 -}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/test/java/dyn/JavaDocExamplesTest.java	Tue Dec 21 18:45:45 2010 -0800
    39.3 @@ -0,0 +1,178 @@
    39.4 +/*
    39.5 + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   39.11 + * particular file as subject to the "Classpath" exception as provided
   39.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   39.25 + * or visit www.oracle.com if you need additional information or have any
   39.26 + * questions.
   39.27 + */
   39.28 +
   39.29 +/* @test
   39.30 + * @summary example code used in javadoc for java.dyn API
   39.31 + * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
   39.32 + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamplesTest
   39.33 + */
   39.34 +
   39.35 +/*
   39.36 +---- To run outside jtreg:
   39.37 +$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
   39.38 +   $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamplesTest.java
   39.39 +$ $JAVA7X_HOME/bin/java   -cp $JUNIT4_JAR:/tmp/Classes \
   39.40 +   -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
   39.41 +   -Dtest.java.dyn.JavaDocExamplesTest.verbosity=1 \
   39.42 +     test.java.dyn.JavaDocExamplesTest
   39.43 +----
   39.44 +*/
   39.45 +
   39.46 +package test.java.dyn;
   39.47 +
   39.48 +import java.dyn.*;
   39.49 +import static java.dyn.MethodHandles.*;
   39.50 +import static java.dyn.MethodType.*;
   39.51 +
   39.52 +import java.lang.reflect.*;
   39.53 +import java.util.*;
   39.54 +
   39.55 +import org.junit.*;
   39.56 +import static org.junit.Assert.*;
   39.57 +import static org.junit.Assume.*;
   39.58 +
   39.59 +
   39.60 +/**
   39.61 + * @author jrose
   39.62 + */
   39.63 +public class JavaDocExamplesTest {
   39.64 +    /** Wrapper for running the JUnit tests in this module.
   39.65 +     *  Put JUnit on the classpath!
   39.66 +     */
   39.67 +    public static void main(String... ignore) {
   39.68 +        org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
   39.69 +    }
   39.70 +    // How much output?
   39.71 +    static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamplesTest.verbosity", 0);
   39.72 +
   39.73 +{}
   39.74 +static final private Lookup LOOKUP = lookup();
   39.75 +// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
   39.76 +//     "concat", methodType(String.class, String.class));
   39.77 +// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
   39.78 +//     "hashCode", methodType(int.class));
   39.79 +
   39.80 +// form required if NoAccessException is intercepted:
   39.81 +static final private MethodHandle CONCAT_2, HASHCODE_2;
   39.82 +static {
   39.83 +  try {
   39.84 +    CONCAT_2 = LOOKUP.findVirtual(String.class,
   39.85 +      "concat", methodType(String.class, String.class));
   39.86 +    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
   39.87 +      "hashCode", methodType(int.class));
   39.88 +   } catch (NoAccessException ex) {
   39.89 +     throw new RuntimeException(ex);
   39.90 +   }
   39.91 +}
   39.92 +{}
   39.93 +
   39.94 +    @Test public void testFindVirtual() throws Throwable {
   39.95 +{}
   39.96 +MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
   39.97 +  "concat", methodType(String.class, String.class));
   39.98 +MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
   39.99 +  "hashCode", methodType(int.class));
  39.100 +//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
  39.101 +assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
  39.102 +assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
  39.103 +//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
  39.104 +assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
  39.105 +assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
  39.106 +{}
  39.107 +    }
  39.108 +    @Test public void testDropArguments() throws Throwable {
  39.109 +        {{
  39.110 +{} /// JAVADOC
  39.111 +MethodHandle cat = lookup().findVirtual(String.class,
  39.112 +  "concat", methodType(String.class, String.class));
  39.113 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
  39.114 +MethodHandle d0 = dropArguments(cat, 0, String.class);
  39.115 +assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
  39.116 +MethodHandle d1 = dropArguments(cat, 1, String.class);
  39.117 +assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
  39.118 +MethodHandle d2 = dropArguments(cat, 2, String.class);
  39.119 +assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
  39.120 +MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
  39.121 +assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
  39.122 +            }}
  39.123 +    }
  39.124 +
  39.125 +    @Test public void testFilterArguments() throws Throwable {
  39.126 +        {{
  39.127 +{} /// JAVADOC
  39.128 +MethodHandle cat = lookup().findVirtual(String.class,
  39.129 +  "concat", methodType(String.class, String.class));
  39.130 +MethodHandle upcase = lookup().findVirtual(String.class,
  39.131 +  "toUpperCase", methodType(String.class));
  39.132 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
  39.133 +MethodHandle f0 = filterArguments(cat, 0, upcase);
  39.134 +assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
  39.135 +MethodHandle f1 = filterArguments(cat, 1, upcase);
  39.136 +assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
  39.137 +MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
  39.138 +assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
  39.139 +            }}
  39.140 +    }
  39.141 +
  39.142 +    static void assertEquals(Object exp, Object act) {
  39.143 +        if (verbosity > 0)
  39.144 +            System.out.println("result: "+act);
  39.145 +        Assert.assertEquals(exp, act);
  39.146 +    }
  39.147 +
  39.148 +static MethodHandle asList;
  39.149 +    @Test public void testWithTypeHandler() throws Throwable {
  39.150 +        {{
  39.151 +{} /// JAVADOC
  39.152 +MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList());
  39.153 +MethodHandle asList = lookup()
  39.154 +  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
  39.155 +
  39.156 +JavaDocExamplesTest.asList = asList;
  39.157 +/*
  39.158 +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) {
  39.159 +  return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType);
  39.160 +}
  39.161 +*/
  39.162 +
  39.163 +MethodHandle collectingTypeHandler = lookup()
  39.164 +  .findStatic(lookup().lookupClass(), "collectingTypeHandler",
  39.165 +     methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
  39.166 +MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler);
  39.167 +
  39.168 +assertEquals("[]", makeAnyList.invokeGeneric().toString());
  39.169 +assertEquals("[1]", makeAnyList.invokeGeneric(1).toString());
  39.170 +assertEquals("[two, too]", makeAnyList.invokeGeneric("two", "too").toString());
  39.171 +            }}
  39.172 +    }
  39.173 +
  39.174 +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) {
  39.175 +    //System.out.println("Converting "+asList+" to "+newType);
  39.176 +    MethodHandle conv = asList.asCollector(Object[].class, newType.parameterCount()).asType(newType);
  39.177 +    //System.out.println(" =>"+conv);
  39.178 +    return conv;
  39.179 +}
  39.180 +
  39.181 +}
    40.1 --- a/test/java/dyn/MethodHandlesTest.java	Tue Dec 21 15:27:55 2010 -0800
    40.2 +++ b/test/java/dyn/MethodHandlesTest.java	Tue Dec 21 18:45:45 2010 -0800
    40.3 @@ -25,8 +25,8 @@
    40.4  
    40.5  /* @test
    40.6   * @summary unit tests for java.dyn.MethodHandles
    40.7 - * @compile -XDinvokedynamic MethodHandlesTest.java
    40.8 - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest
    40.9 + * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
   40.10 + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodHandlesTest
   40.11   */
   40.12  
   40.13  package test.java.dyn;
   40.14 @@ -62,7 +62,6 @@
   40.15      // lookups, without exercising the actual method handle.
   40.16      static boolean DO_MORE_CALLS = true;
   40.17  
   40.18 -
   40.19      @Test
   40.20      public void testFirst() throws Throwable {
   40.21          verbosity += 9; try {
   40.22 @@ -458,7 +457,7 @@
   40.23          Exception noAccess = null;
   40.24          try {
   40.25              if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   40.26 -            target = lookup.findStatic(defc, name, type);
   40.27 +            target = lookup.in(defc).findStatic(defc, name, type);
   40.28          } catch (NoAccessException ex) {
   40.29              noAccess = ex;
   40.30          }
   40.31 @@ -469,16 +468,22 @@
   40.32          assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   40.33          if (!positive)  return; // negative test failed as expected
   40.34          assertEquals(type, target.type());
   40.35 -        assertTrue(target.toString().contains(name));  // rough check
   40.36 +        assertNameStringContains(target, name);
   40.37          if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   40.38          Object[] args = randomArgs(params);
   40.39          printCalled(target, name, args);
   40.40 -        target.invokeVarargs(args);
   40.41 +        target.invokeWithArguments(args);
   40.42          assertCalled(name, args);
   40.43          if (verbosity >= 1)
   40.44              System.out.print(':');
   40.45      }
   40.46  
   40.47 +    // rough check of name string
   40.48 +    static void assertNameStringContains(Object x, String s) {
   40.49 +        if (x.toString().contains(s))  return;
   40.50 +        assertEquals(s, x);
   40.51 +    }
   40.52 +
   40.53      @Test
   40.54      public void testFindVirtual() throws Throwable {
   40.55          if (CAN_SKIP_WORKING)  return;
   40.56 @@ -522,7 +527,7 @@
   40.57          Exception noAccess = null;
   40.58          try {
   40.59              if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   40.60 -            target = lookup.findVirtual(defc, methodName, type);
   40.61 +            target = lookup.in(defc).findVirtual(defc, methodName, type);
   40.62          } catch (NoAccessException ex) {
   40.63              noAccess = ex;
   40.64          }
   40.65 @@ -535,12 +540,12 @@
   40.66          Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
   40.67          MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   40.68          assertEquals(typeWithSelf, target.type());
   40.69 -        assertTrue(target.toString().contains(methodName));  // rough check
   40.70 +        assertNameStringContains(target, methodName);
   40.71          if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   40.72          Object[] argsWithSelf = randomArgs(paramsWithSelf);
   40.73          if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
   40.74          printCalled(target, name, argsWithSelf);
   40.75 -        target.invokeVarargs(argsWithSelf);
   40.76 +        target.invokeWithArguments(argsWithSelf);
   40.77          assertCalled(name, argsWithSelf);
   40.78          if (verbosity >= 1)
   40.79              System.out.print(':');
   40.80 @@ -576,7 +581,8 @@
   40.81          Exception noAccess = null;
   40.82          try {
   40.83              if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   40.84 -            target = lookup.findSpecial(defc, name, type, specialCaller);
   40.85 +            if (verbosity >= 5)  System.out.println("  lookup => "+lookup.in(specialCaller));
   40.86 +            target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller);
   40.87          } catch (NoAccessException ex) {
   40.88              noAccess = ex;
   40.89          }
   40.90 @@ -591,11 +597,11 @@
   40.91          assertEquals(type,          target.type().dropParameterTypes(0,1));
   40.92          Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
   40.93          MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   40.94 -        assertTrue(target.toString().contains(name));  // rough check
   40.95 +        assertNameStringContains(target, name);
   40.96          if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE)  return;
   40.97          Object[] args = randomArgs(paramsWithSelf);
   40.98          printCalled(target, name, args);
   40.99 -        target.invokeVarargs(args);
  40.100 +        target.invokeWithArguments(args);
  40.101          assertCalled(name, args);
  40.102      }
  40.103  
  40.104 @@ -632,7 +638,7 @@
  40.105          Exception noAccess = null;
  40.106          try {
  40.107              if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
  40.108 -            target = lookup.bind(receiver, methodName, type);
  40.109 +            target = lookup.in(defc).bind(receiver, methodName, type);
  40.110          } catch (NoAccessException ex) {
  40.111              noAccess = ex;
  40.112          }
  40.113 @@ -645,7 +651,7 @@
  40.114          assertEquals(type, target.type());
  40.115          Object[] args = randomArgs(params);
  40.116          printCalled(target, name, args);
  40.117 -        target.invokeVarargs(args);
  40.118 +        target.invokeWithArguments(args);
  40.119          Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
  40.120          assertCalled(name, argsWithReceiver);
  40.121          if (verbosity >= 1)
  40.122 @@ -705,9 +711,9 @@
  40.123          try {
  40.124              if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
  40.125              if (isSpecial)
  40.126 -                target = lookup.unreflectSpecial(rmethod, specialCaller);
  40.127 +                target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller);
  40.128              else
  40.129 -                target = lookup.unreflect(rmethod);
  40.130 +                target = lookup.in(defc).unreflect(rmethod);
  40.131          } catch (NoAccessException ex) {
  40.132              noAccess = ex;
  40.133          }
  40.134 @@ -737,7 +743,7 @@
  40.135          }
  40.136          Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
  40.137          printCalled(target, name, argsMaybeWithSelf);
  40.138 -        target.invokeVarargs(argsMaybeWithSelf);
  40.139 +        target.invokeWithArguments(argsMaybeWithSelf);
  40.140          assertCalled(name, argsMaybeWithSelf);
  40.141          if (verbosity >= 1)
  40.142              System.out.print(':');
  40.143 @@ -875,7 +881,7 @@
  40.144          if (isStatic)  expType = expType.dropParameterTypes(0, 1);
  40.145          MethodHandle mh = lookup.unreflectGetter(f);
  40.146          assertSame(mh.type(), expType);
  40.147 -        assertEquals(mh.toString(), fname);
  40.148 +        assertNameStringContains(mh, fname);
  40.149          HasFields fields = new HasFields();
  40.150          Object sawValue;
  40.151          Class<?> rtype = type;
  40.152 @@ -885,12 +891,12 @@
  40.153          for (int i = 0; i <= 1; i++) {
  40.154              if (isStatic) {
  40.155                  if (type == int.class)
  40.156 -                    sawValue = mh.<int>invokeExact();  // do these exactly
  40.157 +                    sawValue = (int) mh.invokeExact();  // do these exactly
  40.158                  else
  40.159                      sawValue = mh.invokeExact();
  40.160              } else {
  40.161                  if (type == int.class)
  40.162 -                    sawValue = mh.<int>invokeExact((Object) fields);
  40.163 +                    sawValue = (int) mh.invokeExact((Object) fields);
  40.164                  else
  40.165                      sawValue = mh.invokeExact((Object) fields);
  40.166              }
  40.167 @@ -947,7 +953,7 @@
  40.168              mh = lookup.findStaticSetter(fclass, fname, ftype);
  40.169          else  throw new InternalError();
  40.170          assertSame(mh.type(), expType);
  40.171 -        assertEquals(mh.toString(), fname);
  40.172 +        assertNameStringContains(mh, fname);
  40.173          HasFields fields = new HasFields();
  40.174          Object sawValue;
  40.175          Class<?> vtype = type;
  40.176 @@ -959,14 +965,14 @@
  40.177              Object putValue = randomArg(type);
  40.178              if (isStatic) {
  40.179                  if (type == int.class)
  40.180 -                    mh.<void>invokeExact((int)(Integer)putValue);  // do these exactly
  40.181 +                    mh.invokeExact((int)putValue);  // do these exactly
  40.182                  else
  40.183 -                    mh.<void>invokeExact(putValue);
  40.184 +                    mh.invokeExact(putValue);
  40.185              } else {
  40.186                  if (type == int.class)
  40.187 -                    mh.<void>invokeExact((Object) fields, (int)(Integer)putValue);
  40.188 +                    mh.invokeExact((Object) fields, (int)putValue);
  40.189                  else
  40.190 -                    mh.<void>invokeExact((Object) fields, putValue);
  40.191 +                    mh.invokeExact((Object) fields, putValue);
  40.192              }
  40.193              assertEquals(f.get(fields), putValue);
  40.194          }
  40.195 @@ -1032,11 +1038,11 @@
  40.196              model.set(i, random);
  40.197              if (testSetter) {
  40.198                  if (elemType == int.class)
  40.199 -                    mh.<void>invokeExact((int[]) array, i, (int)(Integer)random);
  40.200 +                    mh.invokeExact((int[]) array, i, (int)random);
  40.201                  else if (elemType == boolean.class)
  40.202 -                    mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random);
  40.203 +                    mh.invokeExact((boolean[]) array, i, (boolean)random);
  40.204                  else
  40.205 -                    mh.<void>invokeExact(array, i, random);
  40.206 +                    mh.invokeExact(array, i, random);
  40.207                  assertEquals(model, array2list(array));
  40.208              } else {
  40.209                  Array.set(array, i, random);
  40.210 @@ -1052,9 +1058,9 @@
  40.211              if (!testSetter) {
  40.212                  expValue = sawValue;
  40.213                  if (elemType == int.class)
  40.214 -                    sawValue = mh.<int>invokeExact((int[]) array, i);
  40.215 +                    sawValue = (int) mh.invokeExact((int[]) array, i);
  40.216                  else if (elemType == boolean.class)
  40.217 -                    sawValue = mh.<boolean>invokeExact((boolean[]) array, i);
  40.218 +                    sawValue = (boolean) mh.invokeExact((boolean[]) array, i);
  40.219                  else
  40.220                      sawValue = mh.invokeExact(array, i);
  40.221                  assertEquals(sawValue, expValue);
  40.222 @@ -1102,6 +1108,18 @@
  40.223          }
  40.224      }
  40.225  
  40.226 +    static MethodHandle typeHandler2(MethodHandle target, MethodType newType) {
  40.227 +        MethodType oldType = target.type();
  40.228 +        int oldArity = oldType.parameterCount();
  40.229 +        int newArity = newType.parameterCount();
  40.230 +        if (newArity < oldArity)
  40.231 +            return MethodHandles.insertArguments(target, oldArity, "OPTIONAL");
  40.232 +        else if (newArity > oldArity)
  40.233 +            return MethodHandles.dropArguments(target, oldArity-1, newType.parameterType(oldArity-1));
  40.234 +        else
  40.235 +            return target;  // attempt no further conversions
  40.236 +    }
  40.237 +
  40.238      @Test
  40.239      public void testConvertArguments() throws Throwable {
  40.240          if (CAN_SKIP_WORKING)  return;
  40.241 @@ -1115,10 +1133,29 @@
  40.242      }
  40.243  
  40.244      void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
  40.245 -        testConvert(true, id, rtype, name, params);
  40.246 +        testConvert(true, false, id, rtype, name, params);
  40.247 +        testConvert(true, true,  id, rtype, name, params);
  40.248      }
  40.249  
  40.250 -    void testConvert(boolean positive, MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
  40.251 +    @Test
  40.252 +    public void testTypeHandler() throws Throwable {
  40.253 +        MethodHandle id = Callee.ofType(1);
  40.254 +        MethodHandle th2 = PRIVATE.findStatic(MethodHandlesTest.class, "typeHandler2",
  40.255 +                               MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
  40.256 +        MethodHandle id2 = id.withTypeHandler(th2);
  40.257 +        testConvert(true,  false, id2, null, "id", Object.class);
  40.258 +        testConvert(true,  true,  id2, null, "id", Object.class);
  40.259 +        if (true)  return;  //FIXME
  40.260 +        testConvert(true,  false, id2, null, "id", String.class);  // FIXME: throws WMT
  40.261 +        testConvert(false, true,  id2, null, "id", String.class);  // FIXME: should not succeed
  40.262 +        testConvert(false, false, id2, null, "id", Object.class, String.class); //FIXME: array[1] line 1164
  40.263 +        testConvert(true,  true,  id2, null, "id", Object.class, String.class);
  40.264 +        testConvert(false, false, id2, null, "id");
  40.265 +        testConvert(true,  true,  id2, null, "id");
  40.266 +    }
  40.267 +
  40.268 +    void testConvert(boolean positive, boolean useAsType,
  40.269 +                     MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
  40.270          countTest(positive);
  40.271          MethodType idType = id.type();
  40.272          if (rtype == null)  rtype = idType.returnType();
  40.273 @@ -1135,7 +1172,7 @@
  40.274              if (src != dst)
  40.275                  convArgs[i] = castToWrapper(convArgs[i], dst);
  40.276          }
  40.277 -        Object convResult = id.invokeVarargs(convArgs);
  40.278 +        Object convResult = id.invokeWithArguments(convArgs);
  40.279          {
  40.280              Class<?> dst = newType.returnType();
  40.281              Class<?> src = idType.returnType();
  40.282 @@ -1145,7 +1182,10 @@
  40.283          MethodHandle target = null;
  40.284          RuntimeException error = null;
  40.285          try {
  40.286 -            target = MethodHandles.convertArguments(id, newType);
  40.287 +            if (useAsType)
  40.288 +                target = MethodHandles.convertArguments(id, newType);
  40.289 +            else
  40.290 +                target = id.asType(newType);
  40.291          } catch (RuntimeException ex) {
  40.292              error = ex;
  40.293          }
  40.294 @@ -1157,7 +1197,7 @@
  40.295          if (!positive)  return; // negative test failed as expected
  40.296          assertEquals(newType, target.type());
  40.297          printCalled(target, id.toString(), args);
  40.298 -        Object result = target.invokeVarargs(args);
  40.299 +        Object result = target.invokeWithArguments(args);
  40.300          assertCalled(name, convArgs);
  40.301          assertEquals(convResult, result);
  40.302          if (verbosity >= 1)
  40.303 @@ -1279,7 +1319,7 @@
  40.304          MethodType outType = MethodType.methodType(Object.class, permTypes);
  40.305          MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType);
  40.306          MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
  40.307 -        Object result = newTarget.invokeVarargs(args);
  40.308 +        Object result = newTarget.invokeWithArguments(args);
  40.309          Object expected = Arrays.asList(permArgs);
  40.310          assertEquals(expected, result);
  40.311      }
  40.312 @@ -1311,19 +1351,19 @@
  40.313          Object[] args = randomArgs(target2.type().parameterArray());
  40.314          // make sure the target does what we think it does:
  40.315          if (pos == 0 && nargs < 5) {
  40.316 -            Object[] check = (Object[]) target.invokeVarargs(args);
  40.317 +            Object[] check = (Object[]) target.invokeWithArguments(args);
  40.318              assertArrayEquals(args, check);
  40.319              switch (nargs) {
  40.320                  case 0:
  40.321 -                    check = target.<Object[]>invokeExact();
  40.322 +                    check = (Object[]) target.invokeExact();
  40.323                      assertArrayEquals(args, check);
  40.324                      break;
  40.325                  case 1:
  40.326 -                    check = target.<Object[]>invokeExact(args[0]);
  40.327 +                    check = (Object[]) target.invokeExact(args[0]);
  40.328                      assertArrayEquals(args, check);
  40.329                      break;
  40.330                  case 2:
  40.331 -                    check = target.<Object[]>invokeExact(args[0], args[1]);
  40.332 +                    check = (Object[]) target.invokeExact(args[0], args[1]);
  40.333                      assertArrayEquals(args, check);
  40.334                      break;
  40.335              }
  40.336 @@ -1337,12 +1377,15 @@
  40.337          MethodHandle result = MethodHandles.spreadArguments(target2, newType);
  40.338          Object[] returnValue;
  40.339          if (pos == 0) {
  40.340 -            Object rawRetVal = result.invokeExact(args);
  40.341 -            returnValue = (Object[]) rawRetVal;
  40.342 +            // In the following line, the first cast implies
  40.343 +            // normal Object return value for the MH call (Object[])->Object,
  40.344 +            // while the second cast dynamically converts to an Object array.
  40.345 +            // Such a double cast is typical of MH.invokeExact.
  40.346 +            returnValue = (Object[]) (Object) result.invokeExact(args);
  40.347          } else {
  40.348              Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
  40.349              args1[pos] = Arrays.copyOfRange(args, pos, args.length);
  40.350 -            returnValue = (Object[]) result.invokeVarargs(args1);
  40.351 +            returnValue = (Object[]) result.invokeWithArguments(args1);
  40.352          }
  40.353          assertArrayEquals(args, returnValue);
  40.354      }
  40.355 @@ -1379,7 +1422,7 @@
  40.356          if (verbosity >= 3)
  40.357              System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
  40.358          MethodHandle result = MethodHandles.collectArguments(target, newType);
  40.359 -        Object[] returnValue = (Object[]) result.invokeVarargs(args);
  40.360 +        Object[] returnValue = (Object[]) result.invokeWithArguments(args);
  40.361  //        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
  40.362  //        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
  40.363  //        collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
  40.364 @@ -1412,7 +1455,7 @@
  40.365          MethodHandle target2 = MethodHandles.insertArguments(target, pos,
  40.366                  (Object[]) argsToInsert.toArray());
  40.367          argsToInsert.clear();  // remove from argsToInsert
  40.368 -        Object res2 = target2.invokeVarargs(argsToPass);
  40.369 +        Object res2 = target2.invokeWithArguments(argsToPass);
  40.370          Object res2List = Arrays.asList((Object[])res2);
  40.371          if (verbosity >= 3)
  40.372              System.out.println("result: "+res2List);
  40.373 @@ -1440,14 +1483,12 @@
  40.374          Object[] argsToPass = randomArgs(nargs, Object.class);
  40.375          if (verbosity >= 3)
  40.376              System.out.println("filter "+target+" at "+pos+" with "+filter);
  40.377 -        MethodHandle[] filters = new MethodHandle[pos*2+1];
  40.378 -        filters[pos] = filter;
  40.379 -        MethodHandle target2 = MethodHandles.filterArguments(target, filters);
  40.380 +        MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter);
  40.381          // Simulate expected effect of filter on arglist:
  40.382          Object[] filteredArgs = argsToPass.clone();
  40.383          filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
  40.384          List<Object> expected = Arrays.asList(filteredArgs);
  40.385 -        Object result = target2.invokeVarargs(argsToPass);
  40.386 +        Object result = target2.invokeWithArguments(argsToPass);
  40.387          if (verbosity >= 3)
  40.388              System.out.println("result: "+result);
  40.389          if (!expected.equals(result))
  40.390 @@ -1472,7 +1513,7 @@
  40.391          if (pos != 0)  return;  // can fold only at pos=0 for now
  40.392          countTest();
  40.393          MethodHandle target = ValueConversions.varargsList(1 + nargs);
  40.394 -        MethodHandle combine = ValueConversions.varargsList(fold);
  40.395 +        MethodHandle combine = ValueConversions.varargsList(fold).asType(MethodType.genericMethodType(fold));
  40.396          List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
  40.397          if (verbosity >= 3)
  40.398              System.out.println("fold "+target+" with "+combine);
  40.399 @@ -1482,9 +1523,9 @@
  40.400          List<Object> argsToFold = expected.subList(pos, pos + fold);
  40.401          if (verbosity >= 3)
  40.402              System.out.println("fold: "+argsToFold+" into "+target2);
  40.403 -        Object foldedArgs = combine.invokeVarargs(argsToFold);
  40.404 +        Object foldedArgs = combine.invokeWithArguments(argsToFold);
  40.405          argsToFold.add(0, foldedArgs);
  40.406 -        Object result = target2.invokeVarargs(argsToPass);
  40.407 +        Object result = target2.invokeWithArguments(argsToPass);
  40.408          if (verbosity >= 3)
  40.409              System.out.println("result: "+result);
  40.410          if (!expected.equals(result))
  40.411 @@ -1516,7 +1557,7 @@
  40.412          for (int i = drop; i > 0; i--) {
  40.413              argsToDrop.add(pos, "blort#"+i);
  40.414          }
  40.415 -        Object res2 = target2.invokeVarargs(argsToDrop);
  40.416 +        Object res2 = target2.invokeWithArguments(argsToDrop);
  40.417          Object res2List = Arrays.asList((Object[])res2);
  40.418          //if (!resList.equals(res2List))
  40.419          //    System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
  40.420 @@ -1572,7 +1613,7 @@
  40.421          countTest();
  40.422          calledLog.clear();
  40.423          inv = MethodHandles.exactInvoker(type);
  40.424 -        result = inv.invokeVarargs(targetPlusArgs);
  40.425 +        result = inv.invokeWithArguments(targetPlusArgs);
  40.426          if (testRetCode)  assertEquals(code, result);
  40.427          assertCalled("invokee", args);
  40.428          // generic invoker
  40.429 @@ -1598,7 +1639,7 @@
  40.430              assertCalled("invokee", args);
  40.431          }
  40.432          calledLog.clear();
  40.433 -        result = inv.invokeVarargs(targetPlusArgs);
  40.434 +        result = inv.invokeWithArguments(targetPlusArgs);
  40.435          if (testRetCode)  assertEquals(code, result);
  40.436          assertCalled("invokee", args);
  40.437          // varargs invoker #0
  40.438 @@ -1640,17 +1681,29 @@
  40.439              List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
  40.440              Object[] tail = tailList.toArray();
  40.441              tailList.clear(); tailList.add(tail);
  40.442 -            result = inv.invokeVarargs(targetPlusVarArgs);
  40.443 +            result = inv.invokeWithArguments(targetPlusVarArgs);
  40.444              if (testRetCode)  assertEquals(code, result);
  40.445              assertCalled("invokee", args);
  40.446          }
  40.447 +
  40.448          // dynamic invoker
  40.449          countTest();
  40.450 -        CallSite site = new CallSite(MethodHandlesTest.class, "foo", type);
  40.451 -        inv = MethodHandles.dynamicInvoker(site);
  40.452 +        CallSite site = new MutableCallSite(type);
  40.453 +        inv = site.dynamicInvoker();
  40.454 +
  40.455 +        // see if we get the result of the original target:
  40.456 +        try {
  40.457 +            result = inv.invokeWithArguments(args);
  40.458 +            assertTrue("should not reach here", false);
  40.459 +        } catch (IllegalStateException ex) {
  40.460 +            String msg = ex.getMessage();
  40.461 +            assertTrue(msg, msg.contains("site"));
  40.462 +        }
  40.463 +
  40.464 +        // set new target after invoker is created, to make sure we track target
  40.465          site.setTarget(target);
  40.466          calledLog.clear();
  40.467 -        result = inv.invokeVarargs(args);
  40.468 +        result = inv.invokeWithArguments(args);
  40.469          if (testRetCode)  assertEquals(code, result);
  40.470          assertCalled("invokee", args);
  40.471      }
  40.472 @@ -1734,7 +1787,7 @@
  40.473              String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
  40.474              if (verbosity >= 3)
  40.475                  System.out.println(logEntry(willCall, argList));
  40.476 -            Object result = mh.invokeVarargs(argList);
  40.477 +            Object result = mh.invokeWithArguments(argList);
  40.478              assertCalled(willCall, argList);
  40.479          }
  40.480      }
  40.481 @@ -1767,16 +1820,17 @@
  40.482          MethodHandle throwOrReturn
  40.483                  = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
  40.484                      MethodType.methodType(Object.class, Object.class, Throwable.class));
  40.485 -        MethodHandle thrower = throwOrReturn;
  40.486 +        MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
  40.487          while (thrower.type().parameterCount() < nargs)
  40.488              thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
  40.489 +        MethodHandle catcher = ValueConversions.varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
  40.490          MethodHandle target = MethodHandles.catchException(thrower,
  40.491 -                thrown.getClass(), ValueConversions.varargsList(1+nargs));
  40.492 +                thrown.getClass(), catcher);
  40.493          assertEquals(thrower.type(), target.type());
  40.494          //System.out.println("catching with "+target+" : "+throwOrReturn);
  40.495          Object[] args = randomArgs(nargs, Object.class);
  40.496          args[1] = (throwIt ? thrown : null);
  40.497 -        Object returned = target.invokeVarargs(args);
  40.498 +        Object returned = target.invokeWithArguments(args);
  40.499          //System.out.println("return from "+target+" : "+returned);
  40.500          if (!throwIt) {
  40.501              assertSame(args[0], returned);
  40.502 @@ -1828,13 +1882,10 @@
  40.503          testCastFailure("unbox/return", 11000);
  40.504      }
  40.505  
  40.506 -    static class Surprise implements MethodHandleProvider {
  40.507 +    static class Surprise {
  40.508          public MethodHandle asMethodHandle() {
  40.509              return VALUE.bindTo(this);
  40.510          }
  40.511 -        public MethodHandle asMethodHandle(MethodType type) {
  40.512 -            return asMethodHandle().asType(type);
  40.513 -        }
  40.514          Object value(Object x) {
  40.515              trace("value", x);
  40.516              if (boo != null)  return boo;
  40.517 @@ -1896,8 +1947,8 @@
  40.518              }
  40.519              if (callee != null) {
  40.520                  callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1));
  40.521 -                surprise = MethodHandles.filterArguments(callee, surprise);
  40.522 -                identity = MethodHandles.filterArguments(callee, identity);
  40.523 +                surprise = MethodHandles.filterArguments(callee, 0, surprise);
  40.524 +                identity = MethodHandles.filterArguments(callee, 0, identity);
  40.525              }
  40.526          }
  40.527          assertNotSame(mode, surprise, surprise0);
  40.528 @@ -1949,7 +2000,7 @@
  40.529          assertEquals(mt, mh.type());
  40.530          assertEquals(Example.class, mh.type().returnType());
  40.531          args = randomArgs(mh.type().parameterArray());
  40.532 -        mh.invokeVarargs(args);
  40.533 +        mh.invokeWithArguments(args);
  40.534          assertCalled(name, args);
  40.535  
  40.536          // Try a virtual method.
  40.537 @@ -1959,7 +2010,7 @@
  40.538          assertEquals(mt, mh.type().dropParameterTypes(0,1));
  40.539          assertTrue(mh.type().parameterList().contains(Example.class));
  40.540          args = randomArgs(mh.type().parameterArray());
  40.541 -        mh.invokeVarargs(args);
  40.542 +        mh.invokeWithArguments(args);
  40.543          assertCalled(name, args);
  40.544      }
  40.545  
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/test/java/dyn/indify/Indify.java	Tue Dec 21 18:45:45 2010 -0800
    41.3 @@ -0,0 +1,1861 @@
    41.4 +/*
    41.5 + * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
   41.11 + * particular file as subject to the "Classpath" exception as provided
   41.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.25 + * or visit www.oracle.com if you need additional information or have any
   41.26 + * questions.
   41.27 + */
   41.28 +
   41.29 +package indify;
   41.30 +
   41.31 +import java.util.*;
   41.32 +import java.io.*;
   41.33 +import java.lang.reflect.Modifier;
   41.34 +import java.util.regex.*;
   41.35 +
   41.36 +/**
   41.37 + * Transform one or more class files to incorporate JSR 292 features,
   41.38 + * such as {@code invokedynamic}.
   41.39 + * <p>
   41.40 + * This is a standalone program in a single source file.
   41.41 + * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
   41.42 + * Copies of this file may show up in multiple locations for standalone usage.
   41.43 + * The primary maintained location of this file is as follows:
   41.44 + * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
   41.45 + * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
   41.46 + * <p>
   41.47 + * Static private methods named MH_x and MT_x (where x is arbitrary)
   41.48 + * must be stereotyped generators of MethodHandle and MethodType
   41.49 + * constants.  All calls to them are transformed to {@code CONSTANT_MethodHandle}
   41.50 + * and {@code CONSTANT_MethodType} "ldc" instructions.
   41.51 + * The stereotyped code must create method types by calls to {@code methodType} or
   41.52 + * {@code fromMethodDescriptorString}.  The "lookup" argument must be created
   41.53 + * by calls to {@code java.dyn.MethodHandles#lookup MethodHandles.lookup}.
   41.54 + * The class and string arguments must be constant.
   41.55 + * The following methods of {@code java.dyn.MethodHandle.Lookup Lookup} are
   41.56 + * allowed for method handle creation: {@code findStatic}, {@code findVirtual},
   41.57 + * {@code findConstructor}, {@code findSpecial},
   41.58 + * {@code findGetter}, {@code findSetter},
   41.59 + * {@code findStaticGetter}, or {@code findStaticSetter}.
   41.60 + * The call to one of these methods must be followed immediately
   41.61 + * by an {@code areturn} instruction.
   41.62 + * The net result of the call to the MH_x or MT_x method must be
   41.63 + * the creation of a constant method handle.  Thus, replacing calls
   41.64 + * to MH_x or MT_x methods by {@code ldc} instructions should leave
   41.65 + * the meaning of the program unchanged.
   41.66 + * <p>
   41.67 + * Static private methods named INDY_x must be stereotyped generators
   41.68 + * of {@code invokedynamic} call sites.
   41.69 + * All calls to them must be immediately followed by
   41.70 + * {@code invokeExact} calls.
   41.71 + * All such pairs of calls are transformed to {@code invokedynamic}
   41.72 + * instructions.  Each INDY_x method must begin with a call to a
   41.73 + * MH_x method, which is taken to be its bootstrap method.
   41.74 + * The method must be immediately invoked (via {@code invokeGeneric}
   41.75 + * on constant lookup, name, and type arguments.  An object array of
   41.76 + * constants may also be appended to the {@code invokeGeneric call}.
   41.77 + * This call must be cast to {@code CallSite}, and the result must be
   41.78 + * immediately followed by a call to {@code dynamicInvoker}, with the
   41.79 + * resulting method handle returned.
   41.80 + * <p>
   41.81 + * The net result of all of these actions is equivalent to the JVM's
   41.82 + * execution of an {@code invokedynamic} instruction in the unlinked state.
   41.83 + * Running this code once should produce the same results as running
   41.84 + * the corresponding {@code invokedynamic} instruction.
   41.85 + * In order to model the caching behavior, the code of an INDY_x
   41.86 + * method is allowed to begin with getstatic, aaload, and if_acmpne
   41.87 + * instructions which load a static method handle value and return it
   41.88 + * if the value is non-null.
   41.89 + * <p>
   41.90 + * Example usage:
   41.91 + * <blockquote><pre>
   41.92 +$ JAVA_HOME=(some recent OpenJDK 7 build)
   41.93 +$ ant
   41.94 +$ $JAVA_HOME/bin/java -cp build/classes indify.Indify --overwrite --dest build/testout build/classes/indify/Example.class
   41.95 +$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/classes indify.Example
   41.96 +MT = (java.lang.Object)java.lang.Object
   41.97 +MH = adder(int,int)java.lang.Integer
   41.98 +adder(1,2) = 3
   41.99 +calling indy:  42
  41.100 +$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/testout indify.Example
  41.101 +(same output as above)
  41.102 + * </pre></blockquote>
  41.103 + * <p>
  41.104 + * Until the format of {@code CONSTANT_InvokeDynamic} entries is finalized,
  41.105 + * the {@code --transitionalJSR292} switch is recommended (and turned on by default).
  41.106 + * <p>
  41.107 + * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
  41.108 + * @author John Rose
  41.109 + */
  41.110 +public class Indify {
  41.111 +    public static void main(String... av) throws IOException {
  41.112 +        new Indify().run(av);
  41.113 +    }
  41.114 +
  41.115 +    public File dest;
  41.116 +    public String[] classpath = {"."};
  41.117 +    public boolean keepgoing = false;
  41.118 +    public boolean expandProperties = false;
  41.119 +    public boolean overwrite = false;
  41.120 +    public boolean quiet = false;
  41.121 +    public boolean verbose = false;
  41.122 +    public boolean transitionalJSR292 = true;  // default to false later
  41.123 +    public boolean all = false;
  41.124 +    public int verifySpecifierCount = -1;
  41.125 +
  41.126 +    public void run(String... av) throws IOException {
  41.127 +        List<String> avl = new ArrayList<>(Arrays.asList(av));
  41.128 +        parseOptions(avl);
  41.129 +        if (avl.isEmpty())
  41.130 +            throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
  41.131 +        if ("--java".equals(avl.get(0))) {
  41.132 +            avl.remove(0);
  41.133 +            try {
  41.134 +                runApplication(avl.toArray(new String[0]));
  41.135 +            } catch (Exception ex) {
  41.136 +                if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
  41.137 +                throw new RuntimeException(ex);
  41.138 +            }
  41.139 +            return;
  41.140 +        }
  41.141 +        Exception err = null;
  41.142 +        for (String a : avl) {
  41.143 +            try {
  41.144 +                indify(a);
  41.145 +            } catch (Exception ex) {
  41.146 +                if (err == null)  err = ex;
  41.147 +                System.err.println("failure on "+a);
  41.148 +                if (!keepgoing)  break;
  41.149 +            }
  41.150 +        }
  41.151 +        if (err != null) {
  41.152 +            if (err instanceof IOException)  throw (IOException) err;
  41.153 +            throw (RuntimeException) err;
  41.154 +        }
  41.155 +    }
  41.156 +
  41.157 +    /** Execute the given application under a class loader which indifies all application classes. */
  41.158 +    public void runApplication(String... av) throws Exception {
  41.159 +        List<String> avl = new ArrayList<>(Arrays.asList(av));
  41.160 +        String mainClassName = avl.remove(0);
  41.161 +        av = avl.toArray(new String[0]);
  41.162 +        Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
  41.163 +        java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
  41.164 +        main.invoke(null, (Object) av);
  41.165 +    }
  41.166 +
  41.167 +    public void parseOptions(List<String> av) throws IOException {
  41.168 +        for (; !av.isEmpty(); av.remove(0)) {
  41.169 +            String a = av.get(0);
  41.170 +            if (a.startsWith("-")) {
  41.171 +                String a2 = null;
  41.172 +                int eq = a.indexOf('=');
  41.173 +                if (eq > 0) {
  41.174 +                    a2 = maybeExpandProperties(a.substring(eq+1));
  41.175 +                    a = a.substring(0, eq+1);
  41.176 +                }
  41.177 +                switch (a) {
  41.178 +                case "--java":
  41.179 +                    return;  // keep this argument
  41.180 +                case "-d": case "--dest": case "-d=": case "--dest=":
  41.181 +                    dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
  41.182 +                    break;
  41.183 +                case "-cp": case "--classpath":
  41.184 +                    classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
  41.185 +                    break;
  41.186 +                case "-k": case "--keepgoing": case "--keepgoing=":
  41.187 +                    keepgoing = booleanOption(a2);  // print errors but keep going
  41.188 +                    break;
  41.189 +                case "--expand-properties": case "--expand-properties=":
  41.190 +                    expandProperties = booleanOption(a2);  // expand property references in subsequent arguments
  41.191 +                    break;
  41.192 +                case "--verify-specifier-count": case "--verify-specifier-count=":
  41.193 +                    verifySpecifierCount = Integer.valueOf(a2);
  41.194 +                    break;
  41.195 +                case "--overwrite": case "--overwrite=":
  41.196 +                    overwrite = booleanOption(a2);  // overwrite output files
  41.197 +                    break;
  41.198 +                case "--all": case "--all=":
  41.199 +                    all = booleanOption(a2);  // copy all classes, even if no patterns
  41.200 +                    break;
  41.201 +                case "-q": case "--quiet": case "--quiet=":
  41.202 +                    quiet = booleanOption(a2);  // less output
  41.203 +                    break;
  41.204 +                case "-v": case "--verbose": case "--verbose=":
  41.205 +                    verbose = booleanOption(a2);  // more output
  41.206 +                    break;
  41.207 +                case "--transitionalJSR292": case "--transitionalJSR292=":
  41.208 +                    transitionalJSR292 = booleanOption(a2);  // use older invokedynamic format
  41.209 +                    break;
  41.210 +                default:
  41.211 +                    throw new IllegalArgumentException("unrecognized flag: "+a);
  41.212 +                }
  41.213 +                continue;
  41.214 +            } else {
  41.215 +                break;
  41.216 +            }
  41.217 +        }
  41.218 +        if (dest == null && !overwrite)
  41.219 +            throw new RuntimeException("no output specified; need --dest d or --overwrite");
  41.220 +        if (expandProperties) {
  41.221 +            for (int i = 0; i < av.size(); i++)
  41.222 +                av.set(i, maybeExpandProperties(av.get(i)));
  41.223 +        }
  41.224 +    }
  41.225 +
  41.226 +    private boolean booleanOption(String s) {
  41.227 +        if (s == null)  return true;
  41.228 +        switch (s) {
  41.229 +        case "true":  case "yes": case "1": return true;
  41.230 +        case "false": case "no":  case "0": return false;
  41.231 +        }
  41.232 +        throw new IllegalArgumentException("unrecognized boolean flag="+s);
  41.233 +    }
  41.234 +
  41.235 +    private String maybeExpandProperties(String s) {
  41.236 +        if (!expandProperties)  return s;
  41.237 +        Set<String> propsDone = new HashSet<>();
  41.238 +        while (s.contains("${")) {
  41.239 +            int lbrk = s.indexOf("${");
  41.240 +            int rbrk = s.indexOf('}', lbrk);
  41.241 +            if (rbrk < 0)  break;
  41.242 +            String prop = s.substring(lbrk+2, rbrk);
  41.243 +            if (!propsDone.add(prop))  break;
  41.244 +            String value = System.getProperty(prop);
  41.245 +            if (verbose)  System.err.println("expanding ${"+prop+"} => "+value);
  41.246 +            if (value == null)  break;
  41.247 +            s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
  41.248 +        }
  41.249 +        return s;
  41.250 +    }
  41.251 +
  41.252 +    public void indify(String a) throws IOException {
  41.253 +        File f = new File(a);
  41.254 +        String fn = f.getName();
  41.255 +        if (fn.endsWith(".class") && f.isFile())
  41.256 +            indifyFile(f, dest);
  41.257 +        else if (fn.endsWith(".jar") && f.isFile())
  41.258 +            indifyJar(f, dest);
  41.259 +        else if (f.isDirectory())
  41.260 +            indifyTree(f, dest);
  41.261 +        else if (!keepgoing)
  41.262 +            throw new RuntimeException("unrecognized file: "+a);
  41.263 +    }
  41.264 +
  41.265 +    private void ensureDirectory(File dir) {
  41.266 +        if (dir.mkdirs() && !quiet)
  41.267 +            System.err.println("created "+dir);
  41.268 +    }
  41.269 +
  41.270 +    public void indifyFile(File f, File dest) throws IOException {
  41.271 +        if (verbose)  System.err.println("reading "+f);
  41.272 +        ClassFile cf = new ClassFile(f);
  41.273 +        Logic logic = new Logic(cf);
  41.274 +        boolean changed = logic.transform();
  41.275 +        logic.reportPatternMethods(quiet, keepgoing);
  41.276 +        if (changed || all) {
  41.277 +            File outfile;
  41.278 +            if (dest != null) {
  41.279 +                ensureDirectory(dest);
  41.280 +                outfile = classPathFile(dest, cf.nameString());
  41.281 +            } else {
  41.282 +                outfile = f;  // overwrite input file, no matter where it is
  41.283 +            }
  41.284 +            cf.writeTo(outfile);
  41.285 +            if (!quiet)  System.err.println("wrote "+outfile);
  41.286 +        }
  41.287 +    }
  41.288 +
  41.289 +    File classPathFile(File pathDir, String className) {
  41.290 +        String qualname = className+".class";
  41.291 +        qualname = qualname.replace('/', File.separatorChar);
  41.292 +        return new File(pathDir, qualname);
  41.293 +    }
  41.294 +
  41.295 +    public void indifyJar(File f, Object dest) throws IOException {
  41.296 +        throw new UnsupportedOperationException("Not yet implemented");
  41.297 +    }
  41.298 +
  41.299 +    public void indifyTree(File f, File dest) throws IOException {
  41.300 +        if (verbose)  System.err.println("reading directory: "+f);
  41.301 +        for (File f2 : f.listFiles(new FilenameFilter() {
  41.302 +                public boolean accept(File dir, String name) {
  41.303 +                    if (name.endsWith(".class"))  return true;
  41.304 +                    if (name.contains("."))  return false;
  41.305 +                    // return true if it might be a package name:
  41.306 +                    return Character.isJavaIdentifierStart(name.charAt(0));
  41.307 +                }})) {
  41.308 +            if (f2.getName().endsWith(".class"))
  41.309 +                indifyFile(f2, dest);
  41.310 +            else if (f2.isDirectory())
  41.311 +                indifyTree(f2, dest);
  41.312 +        }
  41.313 +    }
  41.314 +
  41.315 +    public ClassLoader makeClassLoader() {
  41.316 +        return new Loader();
  41.317 +    }
  41.318 +    private class Loader extends ClassLoader {
  41.319 +        Loader() {
  41.320 +            this(Indify.class.getClassLoader());
  41.321 +        }
  41.322 +        Loader(ClassLoader parent) {
  41.323 +            super(parent);
  41.324 +        }
  41.325 +        public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  41.326 +            File f = findClassInPath(name);
  41.327 +            if (f != null) {
  41.328 +                try {
  41.329 +                    Class<?> c = transformAndLoadClass(f);
  41.330 +                    if (c != null) {
  41.331 +                        if (resolve)  resolveClass(c);
  41.332 +                        return c;
  41.333 +                    }
  41.334 +                } catch (Exception ex) {
  41.335 +                    if (ex instanceof IllegalArgumentException)
  41.336 +                        // pass error from reportPatternMethods
  41.337 +                        throw (IllegalArgumentException) ex;
  41.338 +                }
  41.339 +            }
  41.340 +            return super.loadClass(name, resolve);
  41.341 +        }
  41.342 +        private File findClassInPath(String name) {
  41.343 +            for (String s : classpath) {
  41.344 +                File f = classPathFile(new File(s), name);
  41.345 +                if (f.exists() && f.canRead()) {
  41.346 +                    return f;
  41.347 +                }
  41.348 +            }
  41.349 +            return null;
  41.350 +        }
  41.351 +        protected Class<?> findClass(String name) throws ClassNotFoundException {
  41.352 +            try {
  41.353 +                return transformAndLoadClass(findClassInPath(name));
  41.354 +            } catch (IOException ex) {
  41.355 +                throw new ClassNotFoundException("IO error", ex);
  41.356 +            }
  41.357 +        }
  41.358 +        private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
  41.359 +            if (verbose)  System.out.println("Loading class from "+f);
  41.360 +            ClassFile cf = new ClassFile(f);
  41.361 +            Logic logic = new Logic(cf);
  41.362 +            boolean changed = logic.transform();
  41.363 +            if (verbose && !changed)  System.out.println("(no change)");
  41.364 +            logic.reportPatternMethods(!verbose, keepgoing);
  41.365 +            byte[] bytes = cf.toByteArray();
  41.366 +            return defineClass(null, bytes, 0, bytes.length);
  41.367 +        }
  41.368 +    }
  41.369 +
  41.370 +    private class Logic {
  41.371 +        // Indify logic, per se.
  41.372 +        ClassFile cf;
  41.373 +        final char[] poolMarks;
  41.374 +        final Map<Method,Constant> constants = new HashMap<>();
  41.375 +        final Map<Method,String> indySignatures = new HashMap<>();
  41.376 +        Logic(ClassFile cf) {
  41.377 +            this.cf = cf;
  41.378 +            poolMarks = new char[cf.pool.size()];
  41.379 +        }
  41.380 +        boolean transform() {
  41.381 +            if (!initializeMarks())  return false;
  41.382 +            if (!findPatternMethods())  return false;
  41.383 +            Pool pool = cf.pool;
  41.384 +            //for (Constant c : cp)  System.out.println("  # "+c);
  41.385 +            for (Method m : cf.methods) {
  41.386 +                if (constants.containsKey(m))  continue;  // don't bother
  41.387 +                // Transform references.
  41.388 +                int blab = 0;
  41.389 +                for (Instruction i = m.instructions(); i != null; i = i.next()) {
  41.390 +                    if (i.bc != opc_invokestatic)  continue;
  41.391 +                    int methi = i.u2At(1);
  41.392 +                    if (poolMarks[methi] == 0)  continue;
  41.393 +                    Short[] ref = pool.getMemberRef((short)methi);
  41.394 +                    Method conm = findMember(cf.methods, ref[1], ref[2]);
  41.395 +                    if (conm == null)  continue;
  41.396 +                    Constant con = constants.get(conm);
  41.397 +                    if (con == null)  continue;
  41.398 +                    if (blab++ == 0 && !quiet)
  41.399 +                        System.err.println("patching "+cf.nameString()+"."+m);
  41.400 +                    //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("  |"+j); }
  41.401 +                    if (con.tag == CONSTANT_InvokeDynamic ||
  41.402 +                        con.tag == CONSTANT_InvokeDynamic_17) {
  41.403 +                        // need to patch the following instruction too,
  41.404 +                        // but there are usually intervening argument pushes too
  41.405 +                        Instruction i2 = findPop(i);
  41.406 +                        Short[] ref2 = null;
  41.407 +                        short ref2i = 0;
  41.408 +                        if (i2 != null && i2.bc == opc_invokevirtual &&
  41.409 +                                poolMarks[(char)(ref2i = (short) i2.u2At(1))] == 'D')
  41.410 +                            ref2 = pool.getMemberRef(ref2i);
  41.411 +                        if (ref2 == null || !"invokeExact".equals(pool.getString(ref2[1]))) {
  41.412 +                            System.err.println(m+": failed to create invokedynamic at "+i.pc);
  41.413 +                            continue;
  41.414 +                        }
  41.415 +                        String invType = pool.getString(ref2[2]);
  41.416 +                        String bsmType = indySignatures.get(conm);
  41.417 +                        if (!invType.equals(bsmType)) {
  41.418 +                            System.err.println(m+": warning: "+conm+" call type and local invoke type differ: "
  41.419 +                                    +bsmType+", "+invType);
  41.420 +                        }
  41.421 +                        assert(i.len == 3 || i2.len == 3);
  41.422 +                        if (!quiet)  System.err.println(i+" "+conm+";...; "+i2+" => invokedynamic "+con);
  41.423 +                        int start = i.pc + 3, end = i2.pc;
  41.424 +                        System.arraycopy(i.codeBase, start, i.codeBase, i.pc, end-start);
  41.425 +                        i.forceNext(0);  // force revisit of new instruction
  41.426 +                        i2.u1AtPut(-3, opc_invokedynamic);
  41.427 +                        i2.u2AtPut(-2, con.index);
  41.428 +                        i2.u2AtPut(0, (short)0);
  41.429 +                        i2.u1AtPut(2, opc_nop);
  41.430 +                        //System.out.println(new Instruction(i.codeBase, i2.pc-3));
  41.431 +                    } else {
  41.432 +                        if (!quiet)  System.err.println(i+" "+conm+" => ldc "+con);
  41.433 +                        assert(i.len == 3);
  41.434 +                        i.u1AtPut(0, opc_ldc_w);
  41.435 +                        i.u2AtPut(1, con.index);
  41.436 +                    }
  41.437 +                }
  41.438 +                //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("    |"+j); }
  41.439 +            }
  41.440 +            cf.methods.removeAll(constants.keySet());
  41.441 +            return true;
  41.442 +        }
  41.443 +
  41.444 +        // Scan forward from the instruction to find where the stack p
  41.445 +        // below the current sp at the instruction.
  41.446 +        Instruction findPop(Instruction i) {
  41.447 +            //System.out.println("findPop from "+i);
  41.448 +            Pool pool = cf.pool;
  41.449 +            JVMState jvm = new JVMState();
  41.450 +        decode:
  41.451 +            for (i = i.clone().next(); i != null; i = i.next()) {
  41.452 +                String pops = INSTRUCTION_POPS[i.bc];
  41.453 +                //System.out.println("  "+i+" "+jvm.stack+" : "+pops.replace("$", " => "));
  41.454 +                if (pops == null)  break;
  41.455 +                if (jvm.stackMotion(i.bc))  continue decode;
  41.456 +                if (pops.indexOf('Q') >= 0) {
  41.457 +                    Short[] ref = pool.getMemberRef((short) i.u2At(1));
  41.458 +                    String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
  41.459 +                    switch (i.bc) {
  41.460 +                    case opc_getstatic:
  41.461 +                    case opc_getfield:
  41.462 +                    case opc_putstatic:
  41.463 +                    case opc_putfield:
  41.464 +                        pops = pops.replace("Q", type);
  41.465 +                        break;
  41.466 +                    default:
  41.467 +                        if (!type.startsWith("("))
  41.468 +                            throw new InternalError(i.toString());
  41.469 +                        pops = pops.replace("Q$Q", type.substring(1).replace(")","$"));
  41.470 +                        break;
  41.471 +                    }
  41.472 +                    //System.out.println("special type: "+type+" => "+pops);
  41.473 +                }
  41.474 +                int npops = pops.indexOf('$');
  41.475 +                if (npops < 0)  throw new InternalError();
  41.476 +                if (npops > jvm.sp())  return i;
  41.477 +                List<Object> args = jvm.args(npops);
  41.478 +                int k = 0;
  41.479 +                for (Object x : args) {
  41.480 +                    char have = (Character) x;
  41.481 +                    char want = pops.charAt(k++);
  41.482 +                    if (have == 'X' || want == 'X')  continue;
  41.483 +                    if (have != want)  break decode;
  41.484 +                }
  41.485 +                if (pops.charAt(k++) != '$')  break decode;
  41.486 +                args.clear();
  41.487 +                while (k < pops.length())
  41.488 +                    args.add(pops.charAt(k++));
  41.489 +            }
  41.490 +            System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
  41.491 +            return null;
  41.492 +        }
  41.493 +
  41.494 +        boolean findPatternMethods() {
  41.495 +            boolean found = false;
  41.496 +            for (char mark : "THI".toCharArray()) {
  41.497 +                for (Method m : cf.methods) {
  41.498 +                    if (!Modifier.isPrivate(m.access))  continue;
  41.499 +                    if (!Modifier.isStatic(m.access))  continue;
  41.500 +                    if (nameAndTypeMark(m.name, m.type) == mark) {
  41.501 +                        Constant con = scanPattern(m, mark);
  41.502 +                        if (con == null)  continue;
  41.503 +                        constants.put(m, con);
  41.504 +                        found = true;
  41.505 +                    }
  41.506 +                }
  41.507 +            }
  41.508 +            return found;
  41.509 +        }
  41.510 +
  41.511 +        void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
  41.512 +            if (!quietly && !constants.keySet().isEmpty())
  41.513 +                System.err.println("pattern methods removed: "+constants.keySet());
  41.514 +            for (Method m : cf.methods) {
  41.515 +                if (nameMark(cf.pool.getString(m.name)) != 0 &&
  41.516 +                    constants.get(m) == null) {
  41.517 +                    String failure = "method has special name but fails to match pattern: "+m;
  41.518 +                    if (!allowMatchFailure)
  41.519 +                        throw new IllegalArgumentException(failure);
  41.520 +                    else if (!quietly)
  41.521 +                        System.err.println("warning: "+failure);
  41.522 +                }
  41.523 +            }
  41.524 +            if (verifySpecifierCount >= 0) {
  41.525 +                List<Object[]> specs = bootstrapMethodSpecifiers(false);
  41.526 +                int specsLen = (specs == null ? 0 : specs.size());
  41.527 +                if (specsLen != verifySpecifierCount) {
  41.528 +                    throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
  41.529 +                }
  41.530 +            }
  41.531 +        }
  41.532 +
  41.533 +        // mark constant pool entries according to participation in patterns
  41.534 +        boolean initializeMarks() {
  41.535 +            boolean changed = false;
  41.536 +            for (;;) {
  41.537 +                boolean changed1 = false;
  41.538 +                int cpindex = -1;
  41.539 +                for (Constant e : cf.pool) {
  41.540 +                    ++cpindex;
  41.541 +                    if (e == null)  continue;
  41.542 +                    char mark = poolMarks[cpindex];
  41.543 +                    if (mark != 0)  continue;
  41.544 +                    switch (e.tag) {
  41.545 +                    case CONSTANT_Utf8:
  41.546 +                        mark = nameMark(e.itemString()); break;
  41.547 +                    case CONSTANT_NameAndType:
  41.548 +                        mark = nameAndTypeMark(e.itemIndexes()); break;
  41.549 +                    case CONSTANT_Class: {
  41.550 +                        int n1 = e.itemIndex();
  41.551 +                        char nmark = poolMarks[(char)n1];
  41.552 +                        if ("DJ".indexOf(nmark) >= 0)
  41.553 +                            mark = nmark;
  41.554 +                        break;
  41.555 +                    }
  41.556 +                    case CONSTANT_Field:
  41.557 +                    case CONSTANT_Method: {
  41.558 +                        Short[] n12 = e.itemIndexes();
  41.559 +                        short cl = n12[0];
  41.560 +                        short nt = n12[1];
  41.561 +                        char cmark = poolMarks[(char)cl];
  41.562 +                        if (cmark != 0) {
  41.563 +                            mark = cmark;  // it is a java.dyn.* or java.lang.* method
  41.564 +                            break;
  41.565 +                        }
  41.566 +                        String cls = cf.pool.getString(CONSTANT_Class, cl);
  41.567 +                        if (cls.equals(cf.nameString())) {
  41.568 +                            switch (poolMarks[(char)nt]) {
  41.569 +                            // it is a private MH/MT/INDY method
  41.570 +                            case 'T': case 'H': case 'I':
  41.571 +                                mark = poolMarks[(char)nt];
  41.572 +                                break;
  41.573 +                            }
  41.574 +                        }
  41.575 +                        break;
  41.576 +                    }
  41.577 +                    default:  break;
  41.578 +                    }
  41.579 +                    if (mark != 0) {
  41.580 +                        poolMarks[cpindex] = mark;
  41.581 +                        changed1 = true;
  41.582 +                    }
  41.583 +                }
  41.584 +                if (!changed1)
  41.585 +                    break;
  41.586 +                changed = true;
  41.587 +            }
  41.588 +            return changed;
  41.589 +        }
  41.590 +        char nameMark(String s) {
  41.591 +            if (s.startsWith("MT_"))                return 'T';
  41.592 +            else if (s.startsWith("MH_"))           return 'H';
  41.593 +            else if (s.startsWith("INDY_"))         return 'I';
  41.594 +            else if (s.startsWith("java/dyn/"))     return 'D';
  41.595 +            else if (s.startsWith("java/lang/"))    return 'J';
  41.596 +            return 0;
  41.597 +        }
  41.598 +        char nameAndTypeMark(Short[] n12) {
  41.599 +            return nameAndTypeMark(n12[0], n12[1]);
  41.600 +        }
  41.601 +        char nameAndTypeMark(short n1, short n2) {
  41.602 +            char mark = poolMarks[(char)n1];
  41.603 +            if (mark == 0)  return 0;
  41.604 +            String descr = cf.pool.getString(CONSTANT_Utf8, n2);
  41.605 +            String requiredType;
  41.606 +            switch (poolMarks[(char)n1]) {
  41.607 +            case 'H': requiredType = "()Ljava/dyn/MethodHandle;";  break;
  41.608 +            case 'T': requiredType = "()Ljava/dyn/MethodType;";    break;
  41.609 +            case 'I': requiredType = "()Ljava/dyn/MethodHandle;";  break;
  41.610 +            default:  return 0;
  41.611 +            }
  41.612 +            if (descr.equals(requiredType))  return mark;
  41.613 +            return 0;
  41.614 +        }
  41.615 +
  41.616 +        private class JVMState {
  41.617 +            final List<Object> stack = new ArrayList<>();
  41.618 +            int sp() { return stack.size(); }
  41.619 +            void push(Object x) { stack.add(x); }
  41.620 +            void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
  41.621 +            void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
  41.622 +            Object pop() { return stack.remove(sp()-1); }
  41.623 +            Object top() { return stack.get(sp()-1); }
  41.624 +            List<Object> args(boolean hasRecv, String type) {
  41.625 +                return args(argsize(type) + (hasRecv ? 1 : 0));
  41.626 +            }
  41.627 +            List<Object> args(int argsize) {
  41.628 +                return stack.subList(sp()-argsize, sp());
  41.629 +            }
  41.630 +            boolean stackMotion(int bc) {
  41.631 +                switch (bc) {
  41.632 +                case opc_pop:    pop();             break;
  41.633 +                case opc_pop2:   pop(); pop();      break;
  41.634 +                case opc_swap:   pushAt(-1, pop()); break;
  41.635 +                case opc_dup:    push(top());       break;
  41.636 +                case opc_dup_x1: pushAt(-2, top()); break;
  41.637 +                case opc_dup_x2: pushAt(-3, top()); break;
  41.638 +                // ? also: dup2{,_x1,_x2}
  41.639 +                default:  return false;
  41.640 +                }
  41.641 +                return true;
  41.642 +            }
  41.643 +        }
  41.644 +        private final String EMPTY_SLOT = "_";
  41.645 +        private void removeEmptyJVMSlots(List<Object> args) {
  41.646 +            for (;;) {
  41.647 +                int i = args.indexOf(EMPTY_SLOT);
  41.648 +                if (i >= 0 && i+1 < args.size()
  41.649 +                    && (isConstant(args.get(i+1), CONSTANT_Long) ||
  41.650 +                        isConstant(args.get(i+1), CONSTANT_Double)))
  41.651 +                    args.remove(i);
  41.652 +                else  break;
  41.653 +            }
  41.654 +        }
  41.655 +
  41.656 +        private Constant scanPattern(Method m, char patternMark) {
  41.657 +            if (verbose)  System.err.println("scan "+m+" for pattern="+patternMark);
  41.658 +            int wantTag;
  41.659 +            switch (patternMark) {
  41.660 +            case 'T': wantTag = CONSTANT_MethodType; break;
  41.661 +            case 'H': wantTag = CONSTANT_MethodHandle; break;
  41.662 +            case 'I': wantTag = CONSTANT_InvokeDynamic; break;
  41.663 +            default: throw new InternalError();
  41.664 +            }
  41.665 +            Instruction i = m.instructions();
  41.666 +            JVMState jvm = new JVMState();
  41.667 +            Pool pool = cf.pool;
  41.668 +            int branchCount = 0;
  41.669 +            Object arg;
  41.670 +            List<Object> args;
  41.671 +            List<Object> bsmArgs = null;  // args to invokeGeneric
  41.672 +        decode:
  41.673 +            for (; i != null; i = i.next()) {
  41.674 +                //System.out.println(jvm.stack+" "+i);
  41.675 +                int bc = i.bc;
  41.676 +                switch (bc) {
  41.677 +                case opc_ldc:           jvm.push(pool.get(i.u1At(1)));   break;
  41.678 +                case opc_ldc_w:         jvm.push(pool.get(i.u2At(1)));   break;
  41.679 +                case opc_ldc2_w:        jvm.push2(pool.get(i.u2At(1)));  break;
  41.680 +                case opc_aconst_null:   jvm.push(null);                  break;
  41.681 +                case opc_bipush:        jvm.push((int)(byte) i.u1At(1)); break;
  41.682 +                case opc_sipush:        jvm.push((int)(short)i.u2At(1)); break;
  41.683 +
  41.684 +                // these support creation of a restarg array
  41.685 +                case opc_anewarray:
  41.686 +                    arg = jvm.pop();
  41.687 +                    if (!(arg instanceof Integer))  break decode;
  41.688 +                    arg = Arrays.asList(new Object[(Integer)arg]);
  41.689 +                    jvm.push(arg);
  41.690 +                    break;
  41.691 +                case opc_dup:
  41.692 +                    jvm.push(jvm.top()); break;
  41.693 +                case opc_aastore:
  41.694 +                    args = jvm.args(3);  // array, index, value
  41.695 +                    if (args.get(0) instanceof List &&
  41.696 +                        args.get(1) instanceof Integer) {
  41.697 +                        ((List<Object>)args.get(0)).set( (Integer)args.get(1), args.get(2) );
  41.698 +                    }
  41.699 +                    args.clear();
  41.700 +                    break;
  41.701 +
  41.702 +                case opc_getstatic:
  41.703 +                {
  41.704 +                    // int.class compiles to getstatic Integer.TYPE
  41.705 +                    int fieldi = i.u2At(1);
  41.706 +                    char mark = poolMarks[fieldi];
  41.707 +                    //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark);
  41.708 +                    if (mark == 'J') {
  41.709 +                        Short[] ref = pool.getMemberRef((short) fieldi);
  41.710 +                        String name = pool.getString(CONSTANT_Utf8, ref[1]);
  41.711 +                        if ("TYPE".equals(name)) {
  41.712 +                            String wrapperName = pool.getString(CONSTANT_Class, ref[0]).replace('/', '.');
  41.713 +                            // a primitive type descriptor
  41.714 +                            Class<?> primClass;
  41.715 +                            try {
  41.716 +                                primClass = (Class<?>) Class.forName(wrapperName).getField(name).get(null);
  41.717 +                            } catch (Exception ex) {
  41.718 +                                throw new InternalError("cannot load "+wrapperName+"."+name);
  41.719 +                            }
  41.720 +                            jvm.push(primClass);
  41.721 +                            break;
  41.722 +                        }
  41.723 +                    }
  41.724 +                    // unknown field; keep going...
  41.725 +                    jvm.push(UNKNOWN_CON);
  41.726 +                    break;
  41.727 +                }
  41.728 +                case opc_putstatic:
  41.729 +                {
  41.730 +                    if (patternMark != 'I')  break decode;
  41.731 +                    jvm.pop();
  41.732 +                    // unknown field; keep going...
  41.733 +                    break;
  41.734 +                }
  41.735 +
  41.736 +                case opc_invokestatic:
  41.737 +                case opc_invokevirtual:
  41.738 +                {
  41.739 +                    boolean hasRecv = (bc == opc_invokevirtual);
  41.740 +                    int methi = i.u2At(1);
  41.741 +                    char mark = poolMarks[methi];
  41.742 +                    Short[] ref = pool.getMemberRef((short)methi);
  41.743 +                    String type = pool.getString(CONSTANT_Utf8, ref[2]);
  41.744 +                    //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type);
  41.745 +                    args = jvm.args(hasRecv, type);
  41.746 +                    String intrinsic = null;
  41.747 +                    Constant con;
  41.748 +                    if (mark == 'D' || mark == 'J') {
  41.749 +                        intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
  41.750 +                        if (mark == 'J') {
  41.751 +                            String cls = pool.getString(CONSTANT_Class, ref[0]);
  41.752 +                            cls = cls.substring(1+cls.lastIndexOf('/'));
  41.753 +                            intrinsic = cls+"."+intrinsic;
  41.754 +                        }
  41.755 +                        //System.out.println("recognized intrinsic "+intrinsic);
  41.756 +                        byte refKind = -1;
  41.757 +                        switch (intrinsic) {
  41.758 +                        case "findGetter":          refKind = REF_getField;         break;
  41.759 +                        case "findStaticGetter":    refKind = REF_getStatic;        break;
  41.760 +                        case "findSetter":          refKind = REF_putField;         break;
  41.761 +                        case "findStaticSetter":    refKind = REF_putStatic;        break;
  41.762 +                        case "findVirtual":         refKind = REF_invokeVirtual;    break;
  41.763 +                        case "findStatic":          refKind = REF_invokeStatic;     break;
  41.764 +                        case "findSpecial":         refKind = REF_invokeSpecial;    break;
  41.765 +                        case "findConstructor":     refKind = REF_newInvokeSpecial; break;
  41.766 +                        }
  41.767 +                        if (refKind >= 0 && (con = parseMemberLookup(refKind, args)) != null) {
  41.768 +                            args.clear(); args.add(con);
  41.769 +                            continue;
  41.770 +                        }
  41.771 +                    }
  41.772 +                    Method ownMethod = null;
  41.773 +                    if (mark == 'T' || mark == 'H' || mark == 'I') {
  41.774 +                        ownMethod = findMember(cf.methods, ref[1], ref[2]);
  41.775 +                    }
  41.776 +                    switch (intrinsic == null ? "" : intrinsic) {
  41.777 +                    case "fromMethodDescriptorString":
  41.778 +                        con = makeMethodTypeCon(args.get(0));
  41.779 +                        args.clear(); args.add(con);
  41.780 +                        continue;
  41.781 +                    case "methodType": {
  41.782 +                        flattenVarargs(args);  // there are several overloadings, some with varargs
  41.783 +                        StringBuilder buf = new StringBuilder();
  41.784 +                        String rtype = null;
  41.785 +                        for (Object typeArg : args) {
  41.786 +                            if (typeArg instanceof Class) {
  41.787 +                                Class<?> argClass = (Class<?>) typeArg;
  41.788 +                                if (argClass.isPrimitive()) {
  41.789 +                                    char tchar;
  41.790 +                                    switch (argClass.getName()) {
  41.791 +                                    case "void":    tchar = 'V'; break;
  41.792 +                                    case "boolean": tchar = 'Z'; break;
  41.793 +                                    case "byte":    tchar = 'B'; break;
  41.794 +                                    case "char":    tchar = 'C'; break;
  41.795 +                                    case "short":   tchar = 'S'; break;
  41.796 +                                    case "int":     tchar = 'I'; break;
  41.797 +                                    case "long":    tchar = 'J'; break;
  41.798 +                                    case "float":   tchar = 'F'; break;
  41.799 +                                    case "double":  tchar = 'D'; break;
  41.800 +                                    default:  throw new InternalError(argClass.toString());
  41.801 +                                    }
  41.802 +                                    buf.append(tchar);
  41.803 +                                } else {
  41.804 +                                    // should not happen, but...
  41.805 +                                    buf.append('L').append(argClass.getName().replace('.','/')).append(';');
  41.806 +                                }
  41.807 +                            } else if (typeArg instanceof Constant) {
  41.808 +                                Constant argCon = (Constant) typeArg;
  41.809 +                                if (argCon.tag == CONSTANT_Class) {
  41.810 +                                    String cn = pool.get(argCon.itemIndex()).itemString();
  41.811 +                                    if (cn.endsWith(";"))
  41.812 +                                        buf.append(cn);
  41.813 +                                    else
  41.814 +                                        buf.append('L').append(cn).append(';');
  41.815 +                                } else {
  41.816 +                                    break decode;
  41.817 +                                }
  41.818 +                            } else {
  41.819 +                                break decode;
  41.820 +                            }
  41.821 +                            if (rtype == null) {
  41.822 +                                // first arg is treated differently
  41.823 +                                rtype = buf.toString();
  41.824 +                                buf.setLength(0);
  41.825 +                                buf.append('(');
  41.826 +                            }
  41.827 +                        }
  41.828 +                        buf.append(')').append(rtype);
  41.829 +                        con = con = makeMethodTypeCon(buf.toString());
  41.830 +                        args.clear(); args.add(con);
  41.831 +                        continue;
  41.832 +                    }
  41.833 +                    case "lookup":
  41.834 +                    case "dynamicInvoker":
  41.835 +                        args.clear(); args.add(intrinsic);
  41.836 +                        continue;
  41.837 +                    case "lookupClass":
  41.838 +                        if (args.equals(Arrays.asList("lookup"))) {
  41.839 +                            // fold lookup().lookupClass() to the enclosing class
  41.840 +                            args.clear(); args.add(pool.get(cf.thisc));
  41.841 +                            continue;
  41.842 +                        }
  41.843 +                        break;
  41.844 +                    case "invokeGeneric":
  41.845 +                    case "invokeWithArguments":
  41.846 +                        if (patternMark != 'I')  break decode;
  41.847 +                        if ("invokeWithArguments".equals(intrinsic))
  41.848 +                            flattenVarargs(args);
  41.849 +                        bsmArgs = new ArrayList(args);
  41.850 +                        args.clear(); args.add("invokeGeneric");
  41.851 +                        continue;
  41.852 +                    case "Integer.valueOf":
  41.853 +                    case "Float.valueOf":
  41.854 +                    case "Long.valueOf":
  41.855 +                    case "Double.valueOf":
  41.856 +                        removeEmptyJVMSlots(args);
  41.857 +                        if (args.size() == 1) {
  41.858 +                            arg = args.remove(0);
  41.859 +                            assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
  41.860 +                            if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
  41.861 +                                || arg instanceof Number) {
  41.862 +                                args.add(arg); continue;
  41.863 +                            }
  41.864 +                        }
  41.865 +                        break decode;
  41.866 +                    }
  41.867 +                    if (!hasRecv && ownMethod != null && patternMark != 0) {
  41.868 +                        con = constants.get(ownMethod);
  41.869 +                        if (con == null)  break decode;
  41.870 +                        args.clear(); args.add(con);
  41.871 +                        continue;
  41.872 +                    } else if (type.endsWith(")V")) {
  41.873 +                        // allow calls like println("reached the pattern method")
  41.874 +                        args.clear();
  41.875 +                        continue;
  41.876 +                    }
  41.877 +                    break decode;  // bail out for most calls
  41.878 +                }
  41.879 +                case opc_areturn:
  41.880 +                {
  41.881 +                    ++branchCount;
  41.882 +                    if (bsmArgs != null) {
  41.883 +                        // parse bsmArgs as (MH, lookup, String, MT, [extra])
  41.884 +                        Constant indyCon = makeInvokeDynamicCon(bsmArgs);
  41.885 +                        if (indyCon != null) {
  41.886 +                            Constant typeCon = (Constant) bsmArgs.get(3);
  41.887 +                            indySignatures.put(m, pool.getString(typeCon.itemIndex()));
  41.888 +                            return indyCon;
  41.889 +                        }
  41.890 +                        System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
  41.891 +                        break decode;  // bail out
  41.892 +                    }
  41.893 +                    arg = jvm.pop();
  41.894 +                    if (branchCount == 2 && UNKNOWN_CON.equals(arg))
  41.895 +                        break;  // merge to next path
  41.896 +                    if (isConstant(arg, wantTag))
  41.897 +                        return (Constant) arg;
  41.898 +                    break decode;  // bail out
  41.899 +                }
  41.900 +                default:
  41.901 +                    if (jvm.stackMotion(i.bc))  break;
  41.902 +                    if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
  41.903 +                        { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
  41.904 +                    if (patternMark == 'I') {
  41.905 +                        // these support caching paths in INDY_x methods
  41.906 +                        if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
  41.907 +                            { jvm.push(UNKNOWN_CON); break; }
  41.908 +                        if (bc == opc_astore || bc >= opc_astore_0 && bc <= opc_astore_MAX)
  41.909 +                            { jvm.pop(); break; }
  41.910 +                        switch (bc) {
  41.911 +                        case opc_getfield:
  41.912 +                        case opc_aaload:
  41.913 +                            jvm.push(UNKNOWN_CON); break;
  41.914 +                        case opc_ifnull:
  41.915 +                        case opc_ifnonnull:
  41.916 +                            // ignore branch target
  41.917 +                            if (++branchCount != 1)  break decode;
  41.918 +                            jvm.pop();
  41.919 +                            break;
  41.920 +                        case opc_checkcast:
  41.921 +                            arg = jvm.top();
  41.922 +                            if ("invokeWithArguments".equals(arg) ||
  41.923 +                                "invokeGeneric".equals(arg))
  41.924 +                                break;  // assume it is a helpful cast
  41.925 +                            break decode;
  41.926 +                        default:
  41.927 +                            break decode;  // bail out
  41.928 +                        }
  41.929 +                        continue decode; // go to next instruction
  41.930 +                    }
  41.931 +                    break decode;  // bail out
  41.932 +                } //end switch
  41.933 +            }
  41.934 +            System.err.println(m+": bailout on "+i+" jvm stack: "+jvm.stack);
  41.935 +            return null;
  41.936 +        }
  41.937 +        private final String UNKNOWN_CON = "<unknown>";
  41.938 +
  41.939 +        private void flattenVarargs(List<Object> args) {
  41.940 +            int size = args.size();
  41.941 +            if (size > 0 && args.get(size-1) instanceof List)
  41.942 +                args.addAll((List<Object>) args.remove(size-1));
  41.943 +        }
  41.944 +
  41.945 +        private boolean isConstant(Object x, int tag) {
  41.946 +            return x instanceof Constant && ((Constant)x).tag == tag;
  41.947 +        }
  41.948 +        private Constant makeMethodTypeCon(Object x) {
  41.949 +            short utfIndex;
  41.950 +            if (x instanceof String)
  41.951 +                utfIndex = (short) cf.pool.addConstant(CONSTANT_Utf8, x).index;
  41.952 +            else if (isConstant(x, CONSTANT_String))
  41.953 +                utfIndex = ((Constant)x).itemIndex();
  41.954 +            else  return null;
  41.955 +            return cf.pool.addConstant(CONSTANT_MethodType, utfIndex);
  41.956 +        }
  41.957 +        private Constant parseMemberLookup(byte refKind, List<Object> args) {
  41.958 +            // E.g.: lookup().findStatic(Foo.class, "name", MethodType)
  41.959 +            if (args.size() != 4)  return null;
  41.960 +            int argi = 0;
  41.961 +            if (!"lookup".equals(args.get(argi++)))  return null;
  41.962 +            short refindex, cindex, ntindex, nindex, tindex;
  41.963 +            Object con;
  41.964 +            if (!isConstant(con = args.get(argi++), CONSTANT_Class))  return null;
  41.965 +            cindex = (short)((Constant)con).index;
  41.966 +            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
  41.967 +            nindex = ((Constant)con).itemIndex();
  41.968 +            if (isConstant(con = args.get(argi++), CONSTANT_MethodType) ||
  41.969 +                isConstant(con, CONSTANT_Class)) {
  41.970 +                tindex = ((Constant)con).itemIndex();
  41.971 +            } else return null;
  41.972 +            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
  41.973 +                    new Short[]{ nindex, tindex }).index;
  41.974 +            byte reftag = CONSTANT_Method;
  41.975 +            if (refKind <= REF_putStatic)
  41.976 +                reftag = CONSTANT_Field;
  41.977 +            else if (refKind == REF_invokeInterface)
  41.978 +                reftag = CONSTANT_InterfaceMethod;
  41.979 +            Constant ref = cf.pool.addConstant(reftag, new Short[]{ cindex, ntindex });
  41.980 +            return cf.pool.addConstant(CONSTANT_MethodHandle, new Object[]{ refKind, (short)ref.index });
  41.981 +        }
  41.982 +        private Constant makeInvokeDynamicCon(List<Object> args) {
  41.983 +            // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
  41.984 +            removeEmptyJVMSlots(args);
  41.985 +            if (args.size() != 4 && args.size() != 5)  return null;
  41.986 +            int argi = 0;
  41.987 +            short nindex, tindex, ntindex, bsmindex;
  41.988 +            Object con;
  41.989 +            if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle))  return null;
  41.990 +            bsmindex = (short) ((Constant)con).index;
  41.991 +            if (!"lookup".equals(args.get(argi++)))  return null;
  41.992 +            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
  41.993 +            nindex = ((Constant)con).itemIndex();
  41.994 +            if (!isConstant(con = args.get(argi++), CONSTANT_MethodType))  return null;
  41.995 +            tindex = ((Constant)con).itemIndex();
  41.996 +            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
  41.997 +                                                  new Short[]{ nindex, tindex }).index;
  41.998 +            if (transitionalJSR292) {
  41.999 +                if (argi != args.size()) {
 41.1000 +                    System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
 41.1001 +                    return null;
 41.1002 +                }
 41.1003 +                return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
 41.1004 +                        new Short[]{ bsmindex, ntindex });
 41.1005 +            }
 41.1006 +            List<Object> extraArgs = Collections.emptyList();
 41.1007 +            if (argi < args.size()) {
 41.1008 +                Object arg = args.get(argi);
 41.1009 +                if (arg instanceof List)
 41.1010 +                    extraArgs = (List<Object>) arg;
 41.1011 +                else
 41.1012 +                    extraArgs = Arrays.asList(arg);
 41.1013 +                removeEmptyJVMSlots(args);
 41.1014 +            }
 41.1015 +            List<Short> extraArgIndexes = new CountedList<>(Short.class);
 41.1016 +            for (Object x : extraArgs) {
 41.1017 +                if (x instanceof Number) {
 41.1018 +                    Object num = null; byte numTag = 0;
 41.1019 +                    if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
 41.1020 +                    if (x instanceof Float)   { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
 41.1021 +                    if (x instanceof Long)    { num = x; numTag = CONSTANT_Long; }
 41.1022 +                    if (x instanceof Double)  { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
 41.1023 +                    if (num != null)  x = cf.pool.addConstant(numTag, x);
 41.1024 +                }
 41.1025 +                if (!(x instanceof Constant))  return null;
 41.1026 +                extraArgIndexes.add((short) ((Constant)x).index);
 41.1027 +            }
 41.1028 +            List<Object[]> specs = bootstrapMethodSpecifiers(true);
 41.1029 +            int specindex = -1;
 41.1030 +            Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
 41.1031 +            for (Object[] spec1 : specs) {
 41.1032 +                if (Arrays.equals(spec1, spec)) {
 41.1033 +                    specindex = specs.indexOf(spec1);
 41.1034 +                    if (verbose)  System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
 41.1035 +                    break;
 41.1036 +                }
 41.1037 +            }
 41.1038 +            if (specindex == -1) {
 41.1039 +                specindex = (short) specs.size();
 41.1040 +                specs.add(spec);
 41.1041 +                if (verbose)  System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
 41.1042 +            }
 41.1043 +            return cf.pool.addConstant(CONSTANT_InvokeDynamic,
 41.1044 +                        new Short[]{ (short)specindex, ntindex });
 41.1045 +        }
 41.1046 +
 41.1047 +        List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
 41.1048 +            Attr bsms = cf.findAttr("BootstrapMethods");
 41.1049 +            if (bsms == null) {
 41.1050 +                if (!createIfNotFound)  return null;
 41.1051 +                bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
 41.1052 +                assert(bsms == cf.findAttr("BootstrapMethods"));
 41.1053 +            }
 41.1054 +            if (bsms.item instanceof byte[]) {
 41.1055 +                // unflatten
 41.1056 +                List<Object[]> specs = new CountedList<>(Object[].class);
 41.1057 +                DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
 41.1058 +                try {
 41.1059 +                    int len = (char) in.readShort();
 41.1060 +                    for (int i = 0; i < len; i++) {
 41.1061 +                        short bsm = in.readShort();
 41.1062 +                        int argc = (char) in.readShort();
 41.1063 +                        List<Short> argv = new CountedList<>(Short.class);
 41.1064 +                        for (int j = 0; j < argc; j++)
 41.1065 +                            argv.add(in.readShort());
 41.1066 +                        specs.add(new Object[]{ bsm, argv });
 41.1067 +                    }
 41.1068 +                } catch (IOException ex) { throw new InternalError(); }
 41.1069 +                bsms.item = specs;
 41.1070 +            }
 41.1071 +            return (List<Object[]>) bsms.item;
 41.1072 +        }
 41.1073 +    }
 41.1074 +
 41.1075 +    private DataInputStream openInput(File f) throws IOException {
 41.1076 +        return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
 41.1077 +    }
 41.1078 +
 41.1079 +    private DataOutputStream openOutput(File f) throws IOException {
 41.1080 +        if (!overwrite && f.exists())
 41.1081 +            throw new IOException("file already exists: "+f);
 41.1082 +        ensureDirectory(f.getParentFile());
 41.1083 +        return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
 41.1084 +    }
 41.1085 +
 41.1086 +    static byte[] readRawBytes(DataInputStream in, int size) throws IOException {
 41.1087 +        byte[] bytes = new byte[size];
 41.1088 +        int nr = in.read(bytes);
 41.1089 +        if (nr != size)
 41.1090 +            throw new InternalError("wrong size: "+nr);
 41.1091 +        return bytes;
 41.1092 +    }
 41.1093 +
 41.1094 +    private interface Chunk {
 41.1095 +        void readFrom(DataInputStream in) throws IOException;
 41.1096 +        void writeTo(DataOutputStream out) throws IOException;
 41.1097 +    }
 41.1098 +
 41.1099 +    private static class CountedList<T> extends ArrayList<T> implements Chunk {
 41.1100 +        final Class<? extends T> itemClass;
 41.1101 +        final int rowlen;
 41.1102 +        CountedList(Class<? extends T> itemClass, int rowlen) {
 41.1103 +            this.itemClass = itemClass;
 41.1104 +            this.rowlen = rowlen;
 41.1105 +        }
 41.1106 +        CountedList(Class<? extends T> itemClass) { this(itemClass, -1); }
 41.1107 +        public void readFrom(DataInputStream in) throws IOException {
 41.1108 +            int count = in.readUnsignedShort();
 41.1109 +            while (size() < count) {
 41.1110 +                if (rowlen < 0) {
 41.1111 +                    add(readInput(in, itemClass));
 41.1112 +                } else {
 41.1113 +                    Class<?> elemClass = itemClass.getComponentType();
 41.1114 +                    Object[] row = (Object[]) java.lang.reflect.Array.newInstance(elemClass, rowlen);
 41.1115 +                    for (int i = 0; i < rowlen; i++)
 41.1116 +                        row[i] = readInput(in, elemClass);
 41.1117 +                    add(itemClass.cast(row));
 41.1118 +                }
 41.1119 +            }
 41.1120 +        }
 41.1121 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1122 +            out.writeShort((short)size());
 41.1123 +            for (T item : this) {
 41.1124 +                writeOutput(out, item);
 41.1125 +            }
 41.1126 +        }
 41.1127 +    }
 41.1128 +
 41.1129 +    private static <T> T readInput(DataInputStream in, Class<T> dataClass) throws IOException {
 41.1130 +        Object data;
 41.1131 +        if (dataClass == Integer.class) {
 41.1132 +            data = in.readInt();
 41.1133 +        } else if (dataClass == Short.class) {
 41.1134 +            data = in.readShort();
 41.1135 +        } else if (dataClass == Byte.class) {
 41.1136 +            data = in.readByte();
 41.1137 +        } else if (dataClass == String.class) {
 41.1138 +            data = in.readUTF();
 41.1139 +        } else if (Chunk.class.isAssignableFrom(dataClass)) {
 41.1140 +            T obj;
 41.1141 +            try { obj = dataClass.newInstance(); }
 41.1142 +                catch (Exception ex) { throw new RuntimeException(ex); }
 41.1143 +            ((Chunk)obj).readFrom(in);
 41.1144 +            data = obj;
 41.1145 +        } else {
 41.1146 +            throw new InternalError("bad input datum: "+dataClass);
 41.1147 +        }
 41.1148 +        return dataClass.cast(data);
 41.1149 +    }
 41.1150 +    private static <T> T readInput(byte[] bytes, Class<T> dataClass) {
 41.1151 +        try {
 41.1152 +            return readInput(new DataInputStream(new ByteArrayInputStream(bytes)), dataClass);
 41.1153 +        } catch (IOException ex) {
 41.1154 +            throw new InternalError();
 41.1155 +        }
 41.1156 +    }
 41.1157 +    private static void readInputs(DataInputStream in, Object... data) throws IOException {
 41.1158 +        for (Object x : data)  ((Chunk)x).readFrom(in);
 41.1159 +    }
 41.1160 +
 41.1161 +    private static void writeOutput(DataOutputStream out, Object data) throws IOException {
 41.1162 +        if (data == null) {
 41.1163 +            return;
 41.1164 +        } if (data instanceof Integer) {
 41.1165 +            out.writeInt((Integer)data);
 41.1166 +        } else if (data instanceof Long) {
 41.1167 +            out.writeLong((Long)data);
 41.1168 +        } else if (data instanceof Short) {
 41.1169 +            out.writeShort((Short)data);
 41.1170 +        } else if (data instanceof Byte) {
 41.1171 +            out.writeByte((Byte)data);
 41.1172 +        } else if (data instanceof String) {
 41.1173 +            out.writeUTF((String)data);
 41.1174 +        } else if (data instanceof byte[]) {
 41.1175 +            out.write((byte[])data);
 41.1176 +        } else if (data instanceof Object[]) {
 41.1177 +            for (Object x : (Object[]) data)
 41.1178 +                writeOutput(out, x);
 41.1179 +        } else if (data instanceof Chunk) {
 41.1180 +            Chunk x = (Chunk) data;
 41.1181 +            x.writeTo(out);
 41.1182 +        } else if (data instanceof List) {
 41.1183 +            for (Object x : (List<?>) data)
 41.1184 +                writeOutput(out, x);
 41.1185 +        } else {
 41.1186 +            throw new InternalError("bad output datum: "+data+" : "+data.getClass().getName());
 41.1187 +        }
 41.1188 +    }
 41.1189 +    private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
 41.1190 +        for (Object x : data)  writeOutput(out, x);
 41.1191 +    }
 41.1192 +
 41.1193 +    public static abstract class Outer {
 41.1194 +        public abstract List<? extends Inner> inners();
 41.1195 +        protected void linkInners() {
 41.1196 +            for (Inner i : inners()) {
 41.1197 +                i.linkOuter(this);
 41.1198 +                if (i instanceof Outer)
 41.1199 +                    ((Outer)i).linkInners();
 41.1200 +            }
 41.1201 +        }
 41.1202 +        public <T extends Outer> T outer(Class<T> c) {
 41.1203 +            for (Outer walk = this;; walk = ((Inner)walk).outer()) {
 41.1204 +                if (c.isInstance(walk))
 41.1205 +                    return c.cast(walk);
 41.1206 +                //if (!(walk instanceof Inner))  return null;
 41.1207 +            }
 41.1208 +        }
 41.1209 +
 41.1210 +        public abstract List<Attr> attrs();
 41.1211 +        public Attr findAttr(String name) {
 41.1212 +            return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
 41.1213 +        }
 41.1214 +        public Attr findAttr(int name) {
 41.1215 +            if (name == 0)  return null;
 41.1216 +            for (Attr a : attrs()) {
 41.1217 +                if (a.name == name)  return a;
 41.1218 +            }
 41.1219 +            return null;
 41.1220 +        }
 41.1221 +    }
 41.1222 +    public interface Inner { Outer outer(); void linkOuter(Outer o); }
 41.1223 +    public static abstract class InnerOuter extends Outer implements Inner {
 41.1224 +        public Outer outer;
 41.1225 +        public Outer outer() { return outer; }
 41.1226 +        public void linkOuter(Outer o) { assert(outer == null); outer = o; }
 41.1227 +    }
 41.1228 +    public static class Constant<T> implements Chunk {
 41.1229 +        public final byte tag;
 41.1230 +        public final T item;
 41.1231 +        public final int index;
 41.1232 +        public Constant(int index, byte tag, T item) {
 41.1233 +            this.index = index;
 41.1234 +            this.tag = tag;
 41.1235 +            this.item = item;
 41.1236 +        }
 41.1237 +        public Constant checkTag(byte tag) {
 41.1238 +            if (this.tag != tag)  throw new InternalError(this.toString());
 41.1239 +            return this;
 41.1240 +        }
 41.1241 +        public String itemString() { return (String)item; }
 41.1242 +        public Short itemIndex() { return (Short)item; }
 41.1243 +        public Short[] itemIndexes() { return (Short[])item; }
 41.1244 +        public void readFrom(DataInputStream in) throws IOException {
 41.1245 +            throw new InternalError("do not call");
 41.1246 +        }
 41.1247 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1248 +            writeOutputs(out, tag, item);
 41.1249 +        }
 41.1250 +        public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
 41.1251 +        public boolean equals(Constant that) {
 41.1252 +            return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
 41.1253 +        }
 41.1254 +        public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
 41.1255 +        public Object itemAsComparable() {
 41.1256 +            switch (tag) {
 41.1257 +            case CONSTANT_Double:   return Double.longBitsToDouble((Long)item);
 41.1258 +            case CONSTANT_Float:    return Float.intBitsToFloat((Integer)item);
 41.1259 +            }
 41.1260 +            return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
 41.1261 +        }
 41.1262 +        public String toString() {
 41.1263 +            String itstr = String.valueOf(itemAsComparable());
 41.1264 +            return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
 41.1265 +        }
 41.1266 +        private static String[] TAG_NAMES;
 41.1267 +        public static String tagName(byte tag) {  // used for error messages
 41.1268 +            if (TAG_NAMES == null)
 41.1269 +                TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
 41.1270 +                             +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
 41.1271 +                             +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
 41.1272 +            if ((tag & 0xFF) >= TAG_NAMES.length)  return "#"+(tag & 0xFF);
 41.1273 +            return TAG_NAMES[tag & 0xFF];
 41.1274 +        }
 41.1275 +    }
 41.1276 +
 41.1277 +    public static class Pool extends CountedList<Constant> implements Chunk {
 41.1278 +        private Map<String,Short> strings = new TreeMap<>();
 41.1279 +
 41.1280 +        public Pool() {
 41.1281 +            super(Constant.class);
 41.1282 +        }
 41.1283 +        public void readFrom(DataInputStream in) throws IOException {
 41.1284 +            int count = in.readUnsignedShort();
 41.1285 +            add(null);  // always ignore first item
 41.1286 +            while (size() < count) {
 41.1287 +                readConstant(in);
 41.1288 +            }
 41.1289 +        }
 41.1290 +        public <T> Constant<T> addConstant(byte tag, T item) {
 41.1291 +            Constant<T> con = new Constant<>(size(), tag, item);
 41.1292 +            int idx = indexOf(con);
 41.1293 +            if (idx >= 0)  return get(idx);
 41.1294 +            add(con);
 41.1295 +            if (tag == CONSTANT_Utf8)  strings.put((String)item, (short) con.index);
 41.1296 +            return con;
 41.1297 +        }
 41.1298 +        private void readConstant(DataInputStream in) throws IOException {
 41.1299 +            byte tag = in.readByte();
 41.1300 +            int index = size();
 41.1301 +            Object arg;
 41.1302 +            switch (tag) {
 41.1303 +            case CONSTANT_Utf8:
 41.1304 +                arg = in.readUTF();
 41.1305 +                strings.put((String) arg, (short) size());
 41.1306 +                break;
 41.1307 +            case CONSTANT_Integer:
 41.1308 +            case CONSTANT_Float:
 41.1309 +                arg = in.readInt(); break;
 41.1310 +            case CONSTANT_Long:
 41.1311 +            case CONSTANT_Double:
 41.1312 +                add(new Constant(index, tag, in.readLong()));
 41.1313 +                add(null);
 41.1314 +                return;
 41.1315 +            case CONSTANT_Class:
 41.1316 +            case CONSTANT_String:
 41.1317 +                arg = in.readShort(); break;
 41.1318 +            case CONSTANT_Field:
 41.1319 +            case CONSTANT_Method:
 41.1320 +            case CONSTANT_InterfaceMethod:
 41.1321 +            case CONSTANT_NameAndType:
 41.1322 +            case CONSTANT_InvokeDynamic_17:
 41.1323 +            case CONSTANT_InvokeDynamic:
 41.1324 +                // read an ordered pair
 41.1325 +                arg = new Short[] { in.readShort(), in.readShort() };
 41.1326 +                break;
 41.1327 +            case CONSTANT_MethodHandle:
 41.1328 +                // read an ordered pair; first part is a u1 (not u2)
 41.1329 +                arg = new Object[] { in.readByte(), in.readShort() };
 41.1330 +                break;
 41.1331 +            case CONSTANT_MethodType:
 41.1332 +                arg = in.readShort(); break;
 41.1333 +            default:
 41.1334 +                throw new InternalError("bad CP tag "+tag);
 41.1335 +            }
 41.1336 +            add(new Constant(index, tag, arg));
 41.1337 +        }
 41.1338 +
 41.1339 +        // Access:
 41.1340 +        public Constant get(int index) {
 41.1341 +            // extra 1-bits get into the shorts
 41.1342 +            return super.get((char) index);
 41.1343 +        }
 41.1344 +        String getString(byte tag, short index) {
 41.1345 +            get(index).checkTag(tag);
 41.1346 +            return getString(index);
 41.1347 +        }
 41.1348 +        String getString(short index) {
 41.1349 +            Object v = get(index).item;
 41.1350 +            if (v instanceof Short)
 41.1351 +                v = get((Short)v).checkTag(CONSTANT_Utf8).item;
 41.1352 +            return (String) v;
 41.1353 +        }
 41.1354 +        String[] getStrings(Short[] indexes) {
 41.1355 +            String[] res = new String[indexes.length];
 41.1356 +            for (int i = 0; i < indexes.length; i++)
 41.1357 +                res[i] = getString(indexes[i]);
 41.1358 +            return res;
 41.1359 +        }
 41.1360 +        int stringIndex(String name, boolean createIfNotFound) {
 41.1361 +            Short x = strings.get(name);
 41.1362 +            if (x != null)  return (char)(int) x;
 41.1363 +            if (!createIfNotFound)  return 0;
 41.1364 +            return addConstant(CONSTANT_Utf8, name).index;
 41.1365 +        }
 41.1366 +        Short[] getMemberRef(short index) {
 41.1367 +            Short[] cls_nnt = get(index).itemIndexes();
 41.1368 +            Short[] name_type = get(cls_nnt[1]).itemIndexes();
 41.1369 +            return new Short[]{ cls_nnt[0], name_type[0], name_type[1] };
 41.1370 +        }
 41.1371 +    }
 41.1372 +
 41.1373 +    public class ClassFile extends Outer implements Chunk {
 41.1374 +        ClassFile(File f) throws IOException {
 41.1375 +            DataInputStream in = openInput(f);
 41.1376 +            try {
 41.1377 +                readFrom(in);
 41.1378 +            } finally {
 41.1379 +                if (in != null)  in.close();
 41.1380 +            }
 41.1381 +        }
 41.1382 +
 41.1383 +        public int                magic, version;  // <min:maj>
 41.1384 +        public final Pool         pool       = new Pool();
 41.1385 +        public short              access, thisc, superc;
 41.1386 +        public final List<Short>  interfaces = new CountedList<>(Short.class);
 41.1387 +        public final List<Field>  fields     = new CountedList<>(Field.class);
 41.1388 +        public final List<Method> methods    = new CountedList<>(Method.class);
 41.1389 +        public final List<Attr>   attrs      = new CountedList<>(Attr.class);
 41.1390 +
 41.1391 +        public final void readFrom(DataInputStream in) throws IOException {
 41.1392 +            magic = in.readInt(); version = in.readInt();
 41.1393 +            if (magic != 0xCAFEBABE)  throw new IOException("bad magic number");
 41.1394 +            pool.readFrom(in);
 41.1395 +            Code_index = pool.stringIndex("Code", false);
 41.1396 +            access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
 41.1397 +            readInputs(in, interfaces, fields, methods, attrs);
 41.1398 +            if (in.read() >= 0)  throw new IOException("junk after end of file");
 41.1399 +            linkInners();
 41.1400 +        }
 41.1401 +
 41.1402 +        void writeTo(File f) throws IOException {
 41.1403 +            DataOutputStream out = openOutput(f);
 41.1404 +            try {
 41.1405 +                writeTo(out);
 41.1406 +            } finally {
 41.1407 +                out.close();
 41.1408 +            }
 41.1409 +        }
 41.1410 +
 41.1411 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1412 +            writeOutputs(out, magic, version, pool,
 41.1413 +                         access, thisc, superc, interfaces,
 41.1414 +                         fields, methods, attrs);
 41.1415 +        }
 41.1416 +
 41.1417 +        public byte[] toByteArray() {
 41.1418 +            try {
 41.1419 +                ByteArrayOutputStream buf = new ByteArrayOutputStream();
 41.1420 +                writeTo(new DataOutputStream(buf));
 41.1421 +                return buf.toByteArray();
 41.1422 +            } catch (IOException ex) {
 41.1423 +                throw new InternalError();
 41.1424 +            }
 41.1425 +        }
 41.1426 +
 41.1427 +        public List<Inner> inners() {
 41.1428 +            List<Inner> inns = new ArrayList<>();
 41.1429 +            inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
 41.1430 +            return inns;
 41.1431 +        }
 41.1432 +        public List<Attr> attrs() { return attrs; }
 41.1433 +
 41.1434 +        // derived stuff:
 41.1435 +        public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
 41.1436 +        int Code_index;
 41.1437 +    }
 41.1438 +
 41.1439 +    private static <T extends Member> T findMember(List<T> mems, int name, int type) {
 41.1440 +        if (name == 0 || type == 0)  return null;
 41.1441 +        for (T m : mems) {
 41.1442 +            if (m.name == name && m.type == type)  return m;
 41.1443 +        }
 41.1444 +        return null;
 41.1445 +    }
 41.1446 +
 41.1447 +    public static class Member extends InnerOuter implements Chunk {
 41.1448 +        public short access, name, type;
 41.1449 +        public final List<Attr> attrs = new CountedList<>(Attr.class);
 41.1450 +        public void readFrom(DataInputStream in) throws IOException {
 41.1451 +            access = in.readShort(); name = in.readShort(); type = in.readShort();
 41.1452 +            readInputs(in, attrs);
 41.1453 +        }
 41.1454 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1455 +            writeOutputs(out, access, name, type, attrs);
 41.1456 +        }
 41.1457 +        public List<Attr> inners() { return attrs; }
 41.1458 +        public List<Attr> attrs() { return attrs; }
 41.1459 +        public ClassFile outer() { return (ClassFile) outer; }
 41.1460 +        public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
 41.1461 +        public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
 41.1462 +        public String toString() {
 41.1463 +            if (outer == null)  return super.toString();
 41.1464 +            return nameString() + (this instanceof Method ? "" : ":")
 41.1465 +                    + simplifyType(typeString());
 41.1466 +        }
 41.1467 +    }
 41.1468 +    public static class Field extends Member {
 41.1469 +    }
 41.1470 +    public static class Method extends Member {
 41.1471 +        public Code code() {
 41.1472 +            Attr a = findAttr("Code");
 41.1473 +            if (a == null)  return null;
 41.1474 +            return (Code) a.item;
 41.1475 +        }
 41.1476 +        public Instruction instructions() {
 41.1477 +            Code code = code();
 41.1478 +            if (code == null)  return null;
 41.1479 +            return code.instructions();
 41.1480 +        }
 41.1481 +    }
 41.1482 +
 41.1483 +    public static class Attr extends InnerOuter implements Chunk {
 41.1484 +        public short name;
 41.1485 +        public int size = -1;  // no pre-declared size
 41.1486 +        public Object item;
 41.1487 +
 41.1488 +        public Attr() {}
 41.1489 +        public Attr(Outer outer, String name, Object item) {
 41.1490 +            ClassFile cf = outer.outer(ClassFile.class);
 41.1491 +            linkOuter(outer);
 41.1492 +            this.name = (short) cf.pool.stringIndex(name, true);
 41.1493 +            this.item = item;
 41.1494 +            outer.attrs().add(this);
 41.1495 +        }
 41.1496 +        public void readFrom(DataInputStream in) throws IOException {
 41.1497 +            name = in.readShort();
 41.1498 +            size = in.readInt();
 41.1499 +            item = readRawBytes(in, size);
 41.1500 +        }
 41.1501 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1502 +            out.writeShort(name);
 41.1503 +            // write the 4-byte size header and then the contents:
 41.1504 +            byte[] bytes;
 41.1505 +            int trueSize;
 41.1506 +            if (item instanceof byte[]) {
 41.1507 +                bytes = (byte[]) item;
 41.1508 +                out.writeInt(trueSize = bytes.length);
 41.1509 +                out.write(bytes);
 41.1510 +            } else {
 41.1511 +                trueSize = flatten(out);
 41.1512 +            }
 41.1513 +            if (trueSize != size && size >= 0)
 41.1514 +                System.err.println("warning: attribute size changed "+size+" to "+trueSize);
 41.1515 +        }
 41.1516 +        public void linkOuter(Outer o) {
 41.1517 +            super.linkOuter(o);
 41.1518 +            if (item instanceof byte[] &&
 41.1519 +                outer instanceof Method &&
 41.1520 +                ((Method)outer).outer().Code_index == name) {
 41.1521 +                    item = readInput((byte[])item, Code.class);
 41.1522 +            }
 41.1523 +        }
 41.1524 +        public List<Inner> inners() {
 41.1525 +            if (item instanceof Inner)
 41.1526 +                return Collections.nCopies(1, (Inner)item);
 41.1527 +            return Collections.emptyList();
 41.1528 +        }
 41.1529 +        public List<Attr> attrs() { return null; }  // Code overrides this
 41.1530 +        public byte[] flatten() {
 41.1531 +            ByteArrayOutputStream buf = new ByteArrayOutputStream(size);
 41.1532 +            flatten(buf);
 41.1533 +            return buf.toByteArray();
 41.1534 +        }
 41.1535 +        public int flatten(DataOutputStream out) throws IOException {
 41.1536 +            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
 41.1537 +            int trueSize = flatten(buf);
 41.1538 +            out.writeInt(trueSize);
 41.1539 +            buf.writeTo(out);
 41.1540 +            return trueSize;
 41.1541 +        }
 41.1542 +        private int flatten(ByteArrayOutputStream buf) {
 41.1543 +            try {
 41.1544 +                writeOutput(new DataOutputStream(buf), item);
 41.1545 +                return buf.size();
 41.1546 +            } catch (IOException ex) {
 41.1547 +                throw new InternalError();
 41.1548 +            }
 41.1549 +        }
 41.1550 +        public String nameString() {
 41.1551 +            ClassFile cf = outer(ClassFile.class);
 41.1552 +            if (cf == null)  return "#"+name;
 41.1553 +            return cf.pool.getString(name);
 41.1554 +        }
 41.1555 +        public String toString() {
 41.1556 +            return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
 41.1557 +        }
 41.1558 +    }
 41.1559 +
 41.1560 +    public static class Code extends InnerOuter implements Chunk {
 41.1561 +        public short stacks, locals;
 41.1562 +        public byte[] bytes;
 41.1563 +        public final List<Short[]> etable = new CountedList<>(Short[].class, 4);
 41.1564 +        public final List<Attr> attrs = new CountedList<>(Attr.class);
 41.1565 +        // etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype }
 41.1566 +        public void readFrom(DataInputStream in) throws IOException {
 41.1567 +            stacks = in.readShort(); locals = in.readShort();
 41.1568 +            bytes = readRawBytes(in, in.readInt());
 41.1569 +            readInputs(in, etable, attrs);
 41.1570 +        }
 41.1571 +        public void writeTo(DataOutputStream out) throws IOException {
 41.1572 +            writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
 41.1573 +        }
 41.1574 +        public List<Attr> inners() { return attrs; }
 41.1575 +        public List<Attr> attrs() { return attrs; }
 41.1576 +        public Instruction instructions() {
 41.1577 +            return new Instruction(bytes, 0);
 41.1578 +        }
 41.1579 +    }
 41.1580 +
 41.1581 +    // lots of constants
 41.1582 +    private static final byte
 41.1583 +        CONSTANT_Utf8              = 1,
 41.1584 +        CONSTANT_Integer           = 3,
 41.1585 +        CONSTANT_Float             = 4,
 41.1586 +        CONSTANT_Long              = 5,
 41.1587 +        CONSTANT_Double            = 6,
 41.1588 +        CONSTANT_Class             = 7,
 41.1589 +        CONSTANT_String            = 8,
 41.1590 +        CONSTANT_Field             = 9,
 41.1591 +        CONSTANT_Method            = 10,
 41.1592 +        CONSTANT_InterfaceMethod   = 11,
 41.1593 +        CONSTANT_NameAndType       = 12,
 41.1594 +        CONSTANT_MethodHandle      = 15,  // JSR 292
 41.1595 +        CONSTANT_MethodType        = 16,  // JSR 292
 41.1596 +        CONSTANT_InvokeDynamic_17  = 17,  // JSR 292, only occurs in old class files
 41.1597 +        CONSTANT_InvokeDynamic     = 18;  // JSR 292
 41.1598 +    private static final byte
 41.1599 +        REF_getField               = 1,
 41.1600 +        REF_getStatic              = 2,
 41.1601 +        REF_putField               = 3,
 41.1602 +        REF_putStatic              = 4,
 41.1603 +        REF_invokeVirtual          = 5,
 41.1604 +        REF_invokeStatic           = 6,
 41.1605 +        REF_invokeSpecial          = 7,
 41.1606 +        REF_newInvokeSpecial       = 8,
 41.1607 +        REF_invokeInterface        = 9;
 41.1608 +
 41.1609 +    private static final int
 41.1610 +        opc_nop                    = 0,
 41.1611 +        opc_aconst_null            = 1,
 41.1612 +        opc_nconst_MIN             = 2,  // iconst_m1
 41.1613 +        opc_nconst_MAX             = 15, // dconst_1
 41.1614 +        opc_bipush                 = 16,
 41.1615 +        opc_sipush                 = 17,
 41.1616 +        opc_ldc                    = 18,
 41.1617 +        opc_ldc_w                  = 19,
 41.1618 +        opc_ldc2_w                 = 20,
 41.1619 +        opc_aload                  = 25,
 41.1620 +        opc_aload_0                = 42,
 41.1621 +        opc_aload_MAX              = 45,
 41.1622 +        opc_aaload                 = 50,
 41.1623 +        opc_astore                 = 58,
 41.1624 +        opc_astore_0               = 75,
 41.1625 +        opc_astore_MAX             = 78,
 41.1626 +        opc_aastore                = 83,
 41.1627 +        opc_pop                    = 87,
 41.1628 +        opc_pop2                   = 88,
 41.1629 +        opc_dup                    = 89,
 41.1630 +        opc_dup_x1                 = 90,
 41.1631 +        opc_dup_x2                 = 91,
 41.1632 +        opc_dup2                   = 92,
 41.1633 +        opc_dup2_x1                = 93,
 41.1634 +        opc_dup2_x2                = 94,
 41.1635 +        opc_swap                   = 95,
 41.1636 +        opc_tableswitch            = 170,
 41.1637 +        opc_lookupswitch           = 171,
 41.1638 +        opc_areturn                = 176,
 41.1639 +        opc_getstatic              = 178,
 41.1640 +        opc_putstatic              = 179,
 41.1641 +        opc_getfield               = 180,
 41.1642 +        opc_putfield               = 181,
 41.1643 +        opc_invokevirtual          = 182,
 41.1644 +        opc_invokespecial          = 183,
 41.1645 +        opc_invokestatic           = 184,
 41.1646 +        opc_invokeinterface        = 185,
 41.1647 +        opc_invokedynamic          = 186,
 41.1648 +        opc_anewarray              = 189,
 41.1649 +        opc_checkcast              = 192,
 41.1650 +        opc_ifnull                 = 198,
 41.1651 +        opc_ifnonnull              = 199,
 41.1652 +        opc_wide                   = 196;
 41.1653 +
 41.1654 +    private static final Object[] INSTRUCTION_CONSTANTS = {
 41.1655 +        -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
 41.1656 +    };
 41.1657 +
 41.1658 +    private static final String INSTRUCTION_FORMATS =
 41.1659 +        "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
 41.1660 +        "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
 41.1661 +        "lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
 41.1662 +        "dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
 41.1663 +        "ldc2_w=bkk$X_ iload=bl/wbll$I lload=bl/wbll$J_ fload=bl/wbll$F "+
 41.1664 +        "dload=bl/wbll$D_ aload=bl/wbll$L iload_0$I iload_1$I "+
 41.1665 +        "iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
 41.1666 +        "lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
 41.1667 +        "dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
 41.1668 +        "aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
 41.1669 +        "daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
 41.1670 +        "istore=bl/wbll$I$ lstore=bl/wbll$J_$ fstore=bl/wbll$F$ "+
 41.1671 +        "dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
 41.1672 +        "istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
 41.1673 +        "lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
 41.1674 +        "fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
 41.1675 +        "dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
 41.1676 +        "iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
 41.1677 +        "aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
 41.1678 +        "pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
 41.1679 +        "dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
 41.1680 +        "iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
 41.1681 +        "lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
 41.1682 +        "fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
 41.1683 +        "ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
 41.1684 +        "ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
 41.1685 +        "ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
 41.1686 +        "land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
 41.1687 +        "iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
 41.1688 +        "l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
 41.1689 +        "d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
 41.1690 +        "ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
 41.1691 +        "if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
 41.1692 +        "if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
 41.1693 +        "goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
 41.1694 +        "ireturn lreturn freturn dreturn areturn return "+
 41.1695 +        "getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
 41.1696 +        "putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
 41.1697 +        "invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
 41.1698 +        "invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
 41.1699 +        "newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
 41.1700 +        "checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
 41.1701 +        "monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
 41.1702 +        "ifnonnull=boo goto_w=boooo jsr_w=boooo ";
 41.1703 +    private static final String[] INSTRUCTION_NAMES;
 41.1704 +    private static final String[] INSTRUCTION_POPS;
 41.1705 +    private static final int[] INSTRUCTION_INFO;
 41.1706 +    static {
 41.1707 +        String[] insns = INSTRUCTION_FORMATS.split(" ");
 41.1708 +        assert(insns[opc_lookupswitch].startsWith("lookupswitch"));
 41.1709 +        assert(insns[opc_tableswitch].startsWith("tableswitch"));
 41.1710 +        assert(insns[opc_wide].startsWith("wide"));
 41.1711 +        assert(insns[opc_invokedynamic].startsWith("invokedynamic"));
 41.1712 +        int[] info = new int[256];
 41.1713 +        String[] names = new String[256];
 41.1714 +        String[] pops = new String[256];
 41.1715 +        for (int i = 0; i < insns.length; i++) {
 41.1716 +            String insn = insns[i];
 41.1717 +            int dl = insn.indexOf('$');
 41.1718 +            if (dl > 0) {
 41.1719 +                String p = insn.substring(dl+1);
 41.1720 +                if (p.indexOf('$') < 0)  p = "$" + p;
 41.1721 +                pops[i] = p;
 41.1722 +                insn = insn.substring(0, dl);
 41.1723 +            }
 41.1724 +            int eq = insn.indexOf('=');
 41.1725 +            if (eq < 0) {
 41.1726 +                info[i] = 1;
 41.1727 +                names[i] = insn;
 41.1728 +                continue;
 41.1729 +            }
 41.1730 +            names[i] = insn.substring(0, eq);
 41.1731 +            String fmt = insn.substring(eq+1);
 41.1732 +            if (fmt.equals("*")) {
 41.1733 +                info[i] = 0;
 41.1734 +                continue;
 41.1735 +            }
 41.1736 +            int sl = fmt.indexOf('/');
 41.1737 +            if (sl < 0) {
 41.1738 +                info[i] = (char) fmt.length();
 41.1739 +            } else {
 41.1740 +                String wfmt = fmt.substring(sl+1);
 41.1741 +                fmt = fmt.substring(0, sl);
 41.1742 +                info[i] = (char)( fmt.length() + (wfmt.length() * 16) );
 41.1743 +            }
 41.1744 +        }
 41.1745 +        INSTRUCTION_INFO = info;
 41.1746 +        INSTRUCTION_NAMES = names;
 41.1747 +        INSTRUCTION_POPS = pops;
 41.1748 +    }
 41.1749 +
 41.1750 +    public static class Instruction implements Cloneable {
 41.1751 +        byte[] codeBase;
 41.1752 +        int pc;
 41.1753 +        int bc;
 41.1754 +        int info;
 41.1755 +        int wide;
 41.1756 +        int len;
 41.1757 +        Instruction(byte[] codeBase, int pc) {
 41.1758 +            this.codeBase = codeBase;
 41.1759 +            init(pc);
 41.1760 +        }
 41.1761 +        public Instruction clone() {
 41.1762 +            try {
 41.1763 +                return (Instruction) super.clone();
 41.1764 +            } catch (CloneNotSupportedException ex) {
 41.1765 +                throw new InternalError();
 41.1766 +            }
 41.1767 +        }
 41.1768 +        private Instruction init(int pc) {
 41.1769 +            this.pc = pc;
 41.1770 +            this.bc = codeBase[pc] & 0xFF;
 41.1771 +            this.info = INSTRUCTION_INFO[bc];
 41.1772 +            this.wide = 0;
 41.1773 +            this.len = (info & 0x0F);
 41.1774 +            if (len == 0)
 41.1775 +                computeLength();
 41.1776 +            return this;
 41.1777 +        }
 41.1778 +        Instruction next() {
 41.1779 +            if (len == 0 && bc != 0)  throw new InternalError();
 41.1780 +            int npc = pc + len;
 41.1781 +            if (npc == codeBase.length)
 41.1782 +                return null;
 41.1783 +            return init(npc);
 41.1784 +        }
 41.1785 +        void forceNext(int newLen) {
 41.1786 +            bc = opc_nop;
 41.1787 +            len = newLen;
 41.1788 +        }
 41.1789 +
 41.1790 +        public String toString() {
 41.1791 +            StringBuilder buf = new StringBuilder();
 41.1792 +            buf.append(pc).append(":").append(INSTRUCTION_NAMES[bc]);
 41.1793 +            switch (len) {
 41.1794 +            case 3: buf.append(" ").append(u2At(1)); break;
 41.1795 +            case 5: buf.append(" ").append(u2At(1)).append(" ").append(u2At(3)); break;
 41.1796 +            default:  for (int i = 1; i < len; i++)  buf.append(" ").append(u1At(1));
 41.1797 +            }
 41.1798 +            return buf.toString();
 41.1799 +        }
 41.1800 +
 41.1801 +        // these are the hard parts
 41.1802 +        private void computeLength() {
 41.1803 +            int cases;
 41.1804 +            switch (bc) {
 41.1805 +            case opc_wide:
 41.1806 +                bc = codeBase[pc + 1];
 41.1807 +                info = INSTRUCTION_INFO[bc];
 41.1808 +                len = ((info >> 4) & 0x0F);
 41.1809 +                if (len == 0)  throw new RuntimeException("misplaced wide bytecode: "+bc);
 41.1810 +                return;
 41.1811 +
 41.1812 +            case opc_tableswitch:
 41.1813 +                cases = (u4At(alignedIntOffset(2)) - u4At(alignedIntOffset(1)) + 1);
 41.1814 +                len = alignedIntOffset(3 + cases*1);
 41.1815 +                return;
 41.1816 +
 41.1817 +            case opc_lookupswitch:
 41.1818 +                cases = u4At(alignedIntOffset(1));
 41.1819 +                len = alignedIntOffset(2 + cases*2);
 41.1820 +                return;
 41.1821 +
 41.1822 +            default:
 41.1823 +                throw new RuntimeException("unknown bytecode: "+bc);
 41.1824 +            }
 41.1825 +        }
 41.1826 +        // switch code
 41.1827 +        // clget the Nth int (where 0 is the first after the opcode itself)
 41.1828 +        public int alignedIntOffset(int n) {
 41.1829 +            int pos = pc + 1;
 41.1830 +            pos += ((-pos) & 0x03);  // align it
 41.1831 +            pos += (n * 4);
 41.1832 +            return pos - pc;
 41.1833 +        }
 41.1834 +        public int u1At(int pos) {
 41.1835 +            return (codeBase[pc+pos] & 0xFF);
 41.1836 +        }
 41.1837 +        public int u2At(int pos) {
 41.1838 +            return (u1At(pos+0)<<8) + u1At(pos+1);
 41.1839 +        }
 41.1840 +        public int u4At(int pos) {
 41.1841 +            return (u2At(pos+0)<<16) + u2At(pos+2);
 41.1842 +        }
 41.1843 +        public void u1AtPut(int pos, int x) {
 41.1844 +            codeBase[pc+pos] = (byte)x;
 41.1845 +        }
 41.1846 +        public void u2AtPut(int pos, int x) {
 41.1847 +            codeBase[pc+pos+0] = (byte)(x >> 8);
 41.1848 +            codeBase[pc+pos+1] = (byte)(x >> 0);
 41.1849 +        }
 41.1850 +    }
 41.1851 +
 41.1852 +    static String simplifyType(String type) {
 41.1853 +        String simpleType = OBJ_SIGNATURE.matcher(type).replaceAll("L");
 41.1854 +        assert(simpleType.matches("^\\([A-Z]*\\)[A-Z]$"));
 41.1855 +        // change (DD)D to (D_D_)D_
 41.1856 +        simpleType = WIDE_SIGNATURE.matcher(simpleType).replaceAll("\\0_");
 41.1857 +        return simpleType;
 41.1858 +    }
 41.1859 +    static int argsize(String type) {
 41.1860 +        return simplifyType(type).length()-3;
 41.1861 +    }
 41.1862 +    private static final Pattern OBJ_SIGNATURE = Pattern.compile("\\[*L[^;]*;|\\[+[A-Z]");
 41.1863 +    private static final Pattern WIDE_SIGNATURE = Pattern.compile("[JD]");
 41.1864 +}