rt/emul/compact/src/main/java/java/lang/invoke/MethodType.java
branchjdk8
changeset 1675 cd50c1894ce5
parent 1674 eca8e9c3ec3e
child 1678 35daab73e225
     1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodType.java	Sun Aug 17 20:09:05 2014 +0200
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1149 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package java.lang.invoke;
    1.30 -
    1.31 -import sun.invoke.util.Wrapper;
    1.32 -import java.lang.ref.WeakReference;
    1.33 -import java.lang.ref.Reference;
    1.34 -import java.lang.ref.ReferenceQueue;
    1.35 -import java.util.Arrays;
    1.36 -import java.util.Collections;
    1.37 -import java.util.List;
    1.38 -import java.util.Objects;
    1.39 -import java.util.concurrent.ConcurrentMap;
    1.40 -import java.util.concurrent.ConcurrentHashMap;
    1.41 -import sun.invoke.util.BytecodeDescriptor;
    1.42 -import static java.lang.invoke.MethodHandleStatics.*;
    1.43 -import sun.invoke.util.VerifyType;
    1.44 -
    1.45 -/**
    1.46 - * A method type represents the arguments and return type accepted and
    1.47 - * returned by a method handle, or the arguments and return type passed
    1.48 - * and expected  by a method handle caller.  Method types must be properly
    1.49 - * matched between a method handle and all its callers,
    1.50 - * and the JVM's operations enforce this matching at, specifically
    1.51 - * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
    1.52 - * and {@link MethodHandle#invoke MethodHandle.invoke}, and during execution
    1.53 - * of {@code invokedynamic} instructions.
    1.54 - * <p>
    1.55 - * The structure is a return type accompanied by any number of parameter types.
    1.56 - * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
    1.57 - * (For ease of exposition, we treat {@code void} as if it were a type.
    1.58 - * In fact, it denotes the absence of a return type.)
    1.59 - * <p>
    1.60 - * All instances of {@code MethodType} are immutable.
    1.61 - * Two instances are completely interchangeable if they compare equal.
    1.62 - * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
    1.63 - * <p>
    1.64 - * This type can be created only by factory methods.
    1.65 - * All factory methods may cache values, though caching is not guaranteed.
    1.66 - * Some factory methods are static, while others are virtual methods which
    1.67 - * modify precursor method types, e.g., by changing a selected parameter.
    1.68 - * <p>
    1.69 - * Factory methods which operate on groups of parameter types
    1.70 - * are systematically presented in two versions, so that both Java arrays and
    1.71 - * Java lists can be used to work with groups of parameter types.
    1.72 - * The query methods {@code parameterArray} and {@code parameterList}
    1.73 - * also provide a choice between arrays and lists.
    1.74 - * <p>
    1.75 - * {@code MethodType} objects are sometimes derived from bytecode instructions
    1.76 - * such as {@code invokedynamic}, specifically from the type descriptor strings associated
    1.77 - * with the instructions in a class file's constant pool.
    1.78 - * <p>
    1.79 - * Like classes and strings, method types can also be represented directly
    1.80 - * in a class file's constant pool as constants.
    1.81 - * A method type may be loaded by an {@code ldc} instruction which refers
    1.82 - * to a suitable {@code CONSTANT_MethodType} constant pool entry.
    1.83 - * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
    1.84 - * (For full details on method type constants,
    1.85 - * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
    1.86 - * <p>
    1.87 - * When the JVM materializes a {@code MethodType} from a descriptor string,
    1.88 - * all classes named in the descriptor must be accessible, and will be loaded.
    1.89 - * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
    1.90 - * This loading may occur at any time before the {@code MethodType} object is first derived.
    1.91 - * @author John Rose, JSR 292 EG
    1.92 - */
    1.93 -public final
    1.94 -class MethodType implements java.io.Serializable {
    1.95 -    private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
    1.96 -
    1.97 -    // The rtype and ptypes fields define the structural identity of the method type:
    1.98 -    private final Class<?>   rtype;
    1.99 -    private final Class<?>[] ptypes;
   1.100 -
   1.101 -    // The remaining fields are caches of various sorts:
   1.102 -    private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
   1.103 -    private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
   1.104 -    private @Stable Invokers invokers;   // cache of handy higher-order adapters
   1.105 -    private @Stable String methodDescriptor;  // cache for toMethodDescriptorString
   1.106 -
   1.107 -    /**
   1.108 -     * Check the given parameters for validity and store them into the final fields.
   1.109 -     */
   1.110 -    private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   1.111 -        checkRtype(rtype);
   1.112 -        checkPtypes(ptypes);
   1.113 -        this.rtype = rtype;
   1.114 -        // defensively copy the array passed in by the user
   1.115 -        this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
   1.116 -    }
   1.117 -
   1.118 -    /**
   1.119 -     * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
   1.120 -     * Does not check the given parameters for validity, and must be discarded after it is used as a searching key.
   1.121 -     * The parameters are reversed for this constructor, so that is is not accidentally used.
   1.122 -     */
   1.123 -    private MethodType(Class<?>[] ptypes, Class<?> rtype) {
   1.124 -        this.rtype = rtype;
   1.125 -        this.ptypes = ptypes;
   1.126 -    }
   1.127 -
   1.128 -    /*trusted*/ MethodTypeForm form() { return form; }
   1.129 -    /*trusted*/ Class<?> rtype() { return rtype; }
   1.130 -    /*trusted*/ Class<?>[] ptypes() { return ptypes; }
   1.131 -
   1.132 -    void setForm(MethodTypeForm f) { form = f; }
   1.133 -
   1.134 -    /** This number, mandated by the JVM spec as 255,
   1.135 -     *  is the maximum number of <em>slots</em>
   1.136 -     *  that any Java method can receive in its argument list.
   1.137 -     *  It limits both JVM signatures and method type objects.
   1.138 -     *  The longest possible invocation will look like
   1.139 -     *  {@code staticMethod(arg1, arg2, ..., arg255)} or
   1.140 -     *  {@code x.virtualMethod(arg1, arg2, ..., arg254)}.
   1.141 -     */
   1.142 -    /*non-public*/ static final int MAX_JVM_ARITY = 255;  // this is mandated by the JVM spec.
   1.143 -
   1.144 -    /** This number is the maximum arity of a method handle, 254.
   1.145 -     *  It is derived from the absolute JVM-imposed arity by subtracting one,
   1.146 -     *  which is the slot occupied by the method handle itself at the
   1.147 -     *  beginning of the argument list used to invoke the method handle.
   1.148 -     *  The longest possible invocation will look like
   1.149 -     *  {@code mh.invoke(arg1, arg2, ..., arg254)}.
   1.150 -     */
   1.151 -    // Issue:  Should we allow MH.invokeWithArguments to go to the full 255?
   1.152 -    /*non-public*/ static final int MAX_MH_ARITY = MAX_JVM_ARITY-1;  // deduct one for mh receiver
   1.153 -
   1.154 -    /** This number is the maximum arity of a method handle invoker, 253.
   1.155 -     *  It is derived from the absolute JVM-imposed arity by subtracting two,
   1.156 -     *  which are the slots occupied by invoke method handle, and the
   1.157 -     *  target method handle, which are both at the beginning of the argument
   1.158 -     *  list used to invoke the target method handle.
   1.159 -     *  The longest possible invocation will look like
   1.160 -     *  {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
   1.161 -     */
   1.162 -    /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1;  // deduct one more for invoker
   1.163 -
   1.164 -    private static void checkRtype(Class<?> rtype) {
   1.165 -        Objects.requireNonNull(rtype);
   1.166 -    }
   1.167 -    private static void checkPtype(Class<?> ptype) {
   1.168 -        Objects.requireNonNull(ptype);
   1.169 -        if (ptype == void.class)
   1.170 -            throw newIllegalArgumentException("parameter type cannot be void");
   1.171 -    }
   1.172 -    /** Return number of extra slots (count of long/double args). */
   1.173 -    private static int checkPtypes(Class<?>[] ptypes) {
   1.174 -        int slots = 0;
   1.175 -        for (Class<?> ptype : ptypes) {
   1.176 -            checkPtype(ptype);
   1.177 -            if (ptype == double.class || ptype == long.class) {
   1.178 -                slots++;
   1.179 -            }
   1.180 -        }
   1.181 -        checkSlotCount(ptypes.length + slots);
   1.182 -        return slots;
   1.183 -    }
   1.184 -    static void checkSlotCount(int count) {
   1.185 -        assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0);
   1.186 -        // MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work:
   1.187 -        if ((count & MAX_JVM_ARITY) != count)
   1.188 -            throw newIllegalArgumentException("bad parameter count "+count);
   1.189 -    }
   1.190 -    private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
   1.191 -        if (num instanceof Integer)  num = "bad index: "+num;
   1.192 -        return new IndexOutOfBoundsException(num.toString());
   1.193 -    }
   1.194 -
   1.195 -    static final ConcurrentWeakInternSet<MethodType> internTable = new ConcurrentWeakInternSet<>();
   1.196 -
   1.197 -    static final Class<?>[] NO_PTYPES = {};
   1.198 -
   1.199 -    /**
   1.200 -     * Finds or creates an instance of the given method type.
   1.201 -     * @param rtype  the return type
   1.202 -     * @param ptypes the parameter types
   1.203 -     * @return a method type with the given components
   1.204 -     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
   1.205 -     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
   1.206 -     */
   1.207 -    public static
   1.208 -    MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
   1.209 -        return makeImpl(rtype, ptypes, false);
   1.210 -    }
   1.211 -
   1.212 -    /**
   1.213 -     * Finds or creates a method type with the given components.
   1.214 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.215 -     * @param rtype  the return type
   1.216 -     * @param ptypes the parameter types
   1.217 -     * @return a method type with the given components
   1.218 -     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
   1.219 -     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
   1.220 -     */
   1.221 -    public static
   1.222 -    MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
   1.223 -        boolean notrust = false;  // random List impl. could return evil ptypes array
   1.224 -        return makeImpl(rtype, listToArray(ptypes), notrust);
   1.225 -    }
   1.226 -
   1.227 -    private static Class<?>[] listToArray(List<Class<?>> ptypes) {
   1.228 -        // sanity check the size before the toArray call, since size might be huge
   1.229 -        checkSlotCount(ptypes.size());
   1.230 -        return ptypes.toArray(NO_PTYPES);
   1.231 -    }
   1.232 -
   1.233 -    /**
   1.234 -     * Finds or creates a method type with the given components.
   1.235 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.236 -     * The leading parameter type is prepended to the remaining array.
   1.237 -     * @param rtype  the return type
   1.238 -     * @param ptype0 the first parameter type
   1.239 -     * @param ptypes the remaining parameter types
   1.240 -     * @return a method type with the given components
   1.241 -     * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
   1.242 -     * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
   1.243 -     */
   1.244 -    public static
   1.245 -    MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
   1.246 -        Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
   1.247 -        ptypes1[0] = ptype0;
   1.248 -        System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
   1.249 -        return makeImpl(rtype, ptypes1, true);
   1.250 -    }
   1.251 -
   1.252 -    /**
   1.253 -     * Finds or creates a method type with the given components.
   1.254 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.255 -     * The resulting method has no parameter types.
   1.256 -     * @param rtype  the return type
   1.257 -     * @return a method type with the given return value
   1.258 -     * @throws NullPointerException if {@code rtype} is null
   1.259 -     */
   1.260 -    public static
   1.261 -    MethodType methodType(Class<?> rtype) {
   1.262 -        return makeImpl(rtype, NO_PTYPES, true);
   1.263 -    }
   1.264 -
   1.265 -    /**
   1.266 -     * Finds or creates a method type with the given components.
   1.267 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.268 -     * The resulting method has the single given parameter type.
   1.269 -     * @param rtype  the return type
   1.270 -     * @param ptype0 the parameter type
   1.271 -     * @return a method type with the given return value and parameter type
   1.272 -     * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
   1.273 -     * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
   1.274 -     */
   1.275 -    public static
   1.276 -    MethodType methodType(Class<?> rtype, Class<?> ptype0) {
   1.277 -        return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
   1.278 -    }
   1.279 -
   1.280 -    /**
   1.281 -     * Finds or creates a method type with the given components.
   1.282 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.283 -     * The resulting method has the same parameter types as {@code ptypes},
   1.284 -     * and the specified return type.
   1.285 -     * @param rtype  the return type
   1.286 -     * @param ptypes the method type which supplies the parameter types
   1.287 -     * @return a method type with the given components
   1.288 -     * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
   1.289 -     */
   1.290 -    public static
   1.291 -    MethodType methodType(Class<?> rtype, MethodType ptypes) {
   1.292 -        return makeImpl(rtype, ptypes.ptypes, true);
   1.293 -    }
   1.294 -
   1.295 -    /**
   1.296 -     * Sole factory method to find or create an interned method type.
   1.297 -     * @param rtype desired return type
   1.298 -     * @param ptypes desired parameter types
   1.299 -     * @param trusted whether the ptypes can be used without cloning
   1.300 -     * @return the unique method type of the desired structure
   1.301 -     */
   1.302 -    /*trusted*/ static
   1.303 -    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   1.304 -        MethodType mt = internTable.get(new MethodType(ptypes, rtype));
   1.305 -        if (mt != null)
   1.306 -            return mt;
   1.307 -        if (ptypes.length == 0) {
   1.308 -            ptypes = NO_PTYPES; trusted = true;
   1.309 -        }
   1.310 -        mt = new MethodType(rtype, ptypes, trusted);
   1.311 -        // promote the object to the Real Thing, and reprobe
   1.312 -        mt.form = MethodTypeForm.findForm(mt);
   1.313 -        return internTable.add(mt);
   1.314 -    }
   1.315 -    private static final MethodType[] objectOnlyTypes = new MethodType[20];
   1.316 -
   1.317 -    /**
   1.318 -     * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
   1.319 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.320 -     * All parameters and the return type will be {@code Object},
   1.321 -     * except the final array parameter if any, which will be {@code Object[]}.
   1.322 -     * @param objectArgCount number of parameters (excluding the final array parameter if any)
   1.323 -     * @param finalArray whether there will be a trailing array parameter, of type {@code Object[]}
   1.324 -     * @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments
   1.325 -     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray} is true)
   1.326 -     * @see #genericMethodType(int)
   1.327 -     */
   1.328 -    public static
   1.329 -    MethodType genericMethodType(int objectArgCount, boolean finalArray) {
   1.330 -        MethodType mt;
   1.331 -        checkSlotCount(objectArgCount);
   1.332 -        int ivarargs = (!finalArray ? 0 : 1);
   1.333 -        int ootIndex = objectArgCount*2 + ivarargs;
   1.334 -        if (ootIndex < objectOnlyTypes.length) {
   1.335 -            mt = objectOnlyTypes[ootIndex];
   1.336 -            if (mt != null)  return mt;
   1.337 -        }
   1.338 -        Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
   1.339 -        Arrays.fill(ptypes, Object.class);
   1.340 -        if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
   1.341 -        mt = makeImpl(Object.class, ptypes, true);
   1.342 -        if (ootIndex < objectOnlyTypes.length) {
   1.343 -            objectOnlyTypes[ootIndex] = mt;     // cache it here also!
   1.344 -        }
   1.345 -        return mt;
   1.346 -    }
   1.347 -
   1.348 -    /**
   1.349 -     * Finds or creates a method type whose components are all {@code Object}.
   1.350 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.351 -     * All parameters and the return type will be Object.
   1.352 -     * @param objectArgCount number of parameters
   1.353 -     * @return a generally applicable method type, for all calls of the given argument count
   1.354 -     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
   1.355 -     * @see #genericMethodType(int, boolean)
   1.356 -     */
   1.357 -    public static
   1.358 -    MethodType genericMethodType(int objectArgCount) {
   1.359 -        return genericMethodType(objectArgCount, false);
   1.360 -    }
   1.361 -
   1.362 -    /**
   1.363 -     * Finds or creates a method type with a single different parameter type.
   1.364 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.365 -     * @param num    the index (zero-based) of the parameter type to change
   1.366 -     * @param nptype a new parameter type to replace the old one with
   1.367 -     * @return the same type, except with the selected parameter changed
   1.368 -     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
   1.369 -     * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
   1.370 -     * @throws NullPointerException if {@code nptype} is null
   1.371 -     */
   1.372 -    public MethodType changeParameterType(int num, Class<?> nptype) {
   1.373 -        if (parameterType(num) == nptype)  return this;
   1.374 -        checkPtype(nptype);
   1.375 -        Class<?>[] nptypes = ptypes.clone();
   1.376 -        nptypes[num] = nptype;
   1.377 -        return makeImpl(rtype, nptypes, true);
   1.378 -    }
   1.379 -
   1.380 -    /**
   1.381 -     * Finds or creates a method type with additional parameter types.
   1.382 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.383 -     * @param num    the position (zero-based) of the inserted parameter type(s)
   1.384 -     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
   1.385 -     * @return the same type, except with the selected parameter(s) inserted
   1.386 -     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
   1.387 -     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
   1.388 -     *                                  or if the resulting method type would have more than 255 parameter slots
   1.389 -     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
   1.390 -     */
   1.391 -    public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
   1.392 -        int len = ptypes.length;
   1.393 -        if (num < 0 || num > len)
   1.394 -            throw newIndexOutOfBoundsException(num);
   1.395 -        int ins = checkPtypes(ptypesToInsert);
   1.396 -        checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
   1.397 -        int ilen = ptypesToInsert.length;
   1.398 -        if (ilen == 0)  return this;
   1.399 -        Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
   1.400 -        System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
   1.401 -        System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
   1.402 -        return makeImpl(rtype, nptypes, true);
   1.403 -    }
   1.404 -
   1.405 -    /**
   1.406 -     * Finds or creates a method type with additional parameter types.
   1.407 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.408 -     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
   1.409 -     * @return the same type, except with the selected parameter(s) appended
   1.410 -     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
   1.411 -     *                                  or if the resulting method type would have more than 255 parameter slots
   1.412 -     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
   1.413 -     */
   1.414 -    public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
   1.415 -        return insertParameterTypes(parameterCount(), ptypesToInsert);
   1.416 -    }
   1.417 -
   1.418 -    /**
   1.419 -     * Finds or creates a method type with additional parameter types.
   1.420 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.421 -     * @param num    the position (zero-based) of the inserted parameter type(s)
   1.422 -     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
   1.423 -     * @return the same type, except with the selected parameter(s) inserted
   1.424 -     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
   1.425 -     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
   1.426 -     *                                  or if the resulting method type would have more than 255 parameter slots
   1.427 -     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
   1.428 -     */
   1.429 -    public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
   1.430 -        return insertParameterTypes(num, listToArray(ptypesToInsert));
   1.431 -    }
   1.432 -
   1.433 -    /**
   1.434 -     * Finds or creates a method type with additional parameter types.
   1.435 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.436 -     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
   1.437 -     * @return the same type, except with the selected parameter(s) appended
   1.438 -     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
   1.439 -     *                                  or if the resulting method type would have more than 255 parameter slots
   1.440 -     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
   1.441 -     */
   1.442 -    public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
   1.443 -        return insertParameterTypes(parameterCount(), ptypesToInsert);
   1.444 -    }
   1.445 -
   1.446 -     /**
   1.447 -     * Finds or creates a method type with modified parameter types.
   1.448 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.449 -     * @param start  the position (zero-based) of the first replaced parameter type(s)
   1.450 -     * @param end    the position (zero-based) after the last replaced parameter type(s)
   1.451 -     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
   1.452 -     * @return the same type, except with the selected parameter(s) replaced
   1.453 -     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
   1.454 -     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
   1.455 -     *                                  or if {@code start} is greater than {@code end}
   1.456 -     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
   1.457 -     *                                  or if the resulting method type would have more than 255 parameter slots
   1.458 -     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
   1.459 -     */
   1.460 -    /*non-public*/ MethodType replaceParameterTypes(int start, int end, Class<?>... ptypesToInsert) {
   1.461 -        if (start == end)
   1.462 -            return insertParameterTypes(start, ptypesToInsert);
   1.463 -        int len = ptypes.length;
   1.464 -        if (!(0 <= start && start <= end && end <= len))
   1.465 -            throw newIndexOutOfBoundsException("start="+start+" end="+end);
   1.466 -        int ilen = ptypesToInsert.length;
   1.467 -        if (ilen == 0)
   1.468 -            return dropParameterTypes(start, end);
   1.469 -        return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
   1.470 -    }
   1.471 -
   1.472 -    /**
   1.473 -     * Finds or creates a method type with some parameter types omitted.
   1.474 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.475 -     * @param start  the index (zero-based) of the first parameter type to remove
   1.476 -     * @param end    the index (greater than {@code start}) of the first parameter type after not to remove
   1.477 -     * @return the same type, except with the selected parameter(s) removed
   1.478 -     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
   1.479 -     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
   1.480 -     *                                  or if {@code start} is greater than {@code end}
   1.481 -     */
   1.482 -    public MethodType dropParameterTypes(int start, int end) {
   1.483 -        int len = ptypes.length;
   1.484 -        if (!(0 <= start && start <= end && end <= len))
   1.485 -            throw newIndexOutOfBoundsException("start="+start+" end="+end);
   1.486 -        if (start == end)  return this;
   1.487 -        Class<?>[] nptypes;
   1.488 -        if (start == 0) {
   1.489 -            if (end == len) {
   1.490 -                // drop all parameters
   1.491 -                nptypes = NO_PTYPES;
   1.492 -            } else {
   1.493 -                // drop initial parameter(s)
   1.494 -                nptypes = Arrays.copyOfRange(ptypes, end, len);
   1.495 -            }
   1.496 -        } else {
   1.497 -            if (end == len) {
   1.498 -                // drop trailing parameter(s)
   1.499 -                nptypes = Arrays.copyOfRange(ptypes, 0, start);
   1.500 -            } else {
   1.501 -                int tail = len - end;
   1.502 -                nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
   1.503 -                System.arraycopy(ptypes, end, nptypes, start, tail);
   1.504 -            }
   1.505 -        }
   1.506 -        return makeImpl(rtype, nptypes, true);
   1.507 -    }
   1.508 -
   1.509 -    /**
   1.510 -     * Finds or creates a method type with a different return type.
   1.511 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.512 -     * @param nrtype a return parameter type to replace the old one with
   1.513 -     * @return the same type, except with the return type change
   1.514 -     * @throws NullPointerException if {@code nrtype} is null
   1.515 -     */
   1.516 -    public MethodType changeReturnType(Class<?> nrtype) {
   1.517 -        if (returnType() == nrtype)  return this;
   1.518 -        return makeImpl(nrtype, ptypes, true);
   1.519 -    }
   1.520 -
   1.521 -    /**
   1.522 -     * Reports if this type contains a primitive argument or return value.
   1.523 -     * The return type {@code void} counts as a primitive.
   1.524 -     * @return true if any of the types are primitives
   1.525 -     */
   1.526 -    public boolean hasPrimitives() {
   1.527 -        return form.hasPrimitives();
   1.528 -    }
   1.529 -
   1.530 -    /**
   1.531 -     * Reports if this type contains a wrapper argument or return value.
   1.532 -     * Wrappers are types which box primitive values, such as {@link Integer}.
   1.533 -     * The reference type {@code java.lang.Void} counts as a wrapper,
   1.534 -     * if it occurs as a return type.
   1.535 -     * @return true if any of the types are wrappers
   1.536 -     */
   1.537 -    public boolean hasWrappers() {
   1.538 -        return unwrap() != this;
   1.539 -    }
   1.540 -
   1.541 -    /**
   1.542 -     * Erases all reference types to {@code Object}.
   1.543 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.544 -     * All primitive types (including {@code void}) will remain unchanged.
   1.545 -     * @return a version of the original type with all reference types replaced
   1.546 -     */
   1.547 -    public MethodType erase() {
   1.548 -        return form.erasedType();
   1.549 -    }
   1.550 -
   1.551 -    /**
   1.552 -     * Erases all reference types to {@code Object}, and all subword types to {@code int}.
   1.553 -     * This is the reduced type polymorphism used by private methods
   1.554 -     * such as {@link MethodHandle#invokeBasic invokeBasic}.
   1.555 -     * @return a version of the original type with all reference and subword types replaced
   1.556 -     */
   1.557 -    /*non-public*/ MethodType basicType() {
   1.558 -        return form.basicType();
   1.559 -    }
   1.560 -
   1.561 -    /**
   1.562 -     * @return a version of the original type with MethodHandle prepended as the first argument
   1.563 -     */
   1.564 -    /*non-public*/ MethodType invokerType() {
   1.565 -        return insertParameterTypes(0, MethodHandle.class);
   1.566 -    }
   1.567 -
   1.568 -    /**
   1.569 -     * Converts all types, both reference and primitive, to {@code Object}.
   1.570 -     * Convenience method for {@link #genericMethodType(int) genericMethodType}.
   1.571 -     * The expression {@code type.wrap().erase()} produces the same value
   1.572 -     * as {@code type.generic()}.
   1.573 -     * @return a version of the original type with all types replaced
   1.574 -     */
   1.575 -    public MethodType generic() {
   1.576 -        return genericMethodType(parameterCount());
   1.577 -    }
   1.578 -
   1.579 -    /**
   1.580 -     * Converts all primitive types to their corresponding wrapper types.
   1.581 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.582 -     * All reference types (including wrapper types) will remain unchanged.
   1.583 -     * A {@code void} return type is changed to the type {@code java.lang.Void}.
   1.584 -     * The expression {@code type.wrap().erase()} produces the same value
   1.585 -     * as {@code type.generic()}.
   1.586 -     * @return a version of the original type with all primitive types replaced
   1.587 -     */
   1.588 -    public MethodType wrap() {
   1.589 -        return hasPrimitives() ? wrapWithPrims(this) : this;
   1.590 -    }
   1.591 -
   1.592 -    /**
   1.593 -     * Converts all wrapper types to their corresponding primitive types.
   1.594 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.595 -     * All primitive types (including {@code void}) will remain unchanged.
   1.596 -     * A return type of {@code java.lang.Void} is changed to {@code void}.
   1.597 -     * @return a version of the original type with all wrapper types replaced
   1.598 -     */
   1.599 -    public MethodType unwrap() {
   1.600 -        MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
   1.601 -        return unwrapWithNoPrims(noprims);
   1.602 -    }
   1.603 -
   1.604 -    private static MethodType wrapWithPrims(MethodType pt) {
   1.605 -        assert(pt.hasPrimitives());
   1.606 -        MethodType wt = pt.wrapAlt;
   1.607 -        if (wt == null) {
   1.608 -            // fill in lazily
   1.609 -            wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
   1.610 -            assert(wt != null);
   1.611 -            pt.wrapAlt = wt;
   1.612 -        }
   1.613 -        return wt;
   1.614 -    }
   1.615 -
   1.616 -    private static MethodType unwrapWithNoPrims(MethodType wt) {
   1.617 -        assert(!wt.hasPrimitives());
   1.618 -        MethodType uwt = wt.wrapAlt;
   1.619 -        if (uwt == null) {
   1.620 -            // fill in lazily
   1.621 -            uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
   1.622 -            if (uwt == null)
   1.623 -                uwt = wt;    // type has no wrappers or prims at all
   1.624 -            wt.wrapAlt = uwt;
   1.625 -        }
   1.626 -        return uwt;
   1.627 -    }
   1.628 -
   1.629 -    /**
   1.630 -     * Returns the parameter type at the specified index, within this method type.
   1.631 -     * @param num the index (zero-based) of the desired parameter type
   1.632 -     * @return the selected parameter type
   1.633 -     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
   1.634 -     */
   1.635 -    public Class<?> parameterType(int num) {
   1.636 -        return ptypes[num];
   1.637 -    }
   1.638 -    /**
   1.639 -     * Returns the number of parameter types in this method type.
   1.640 -     * @return the number of parameter types
   1.641 -     */
   1.642 -    public int parameterCount() {
   1.643 -        return ptypes.length;
   1.644 -    }
   1.645 -    /**
   1.646 -     * Returns the return type of this method type.
   1.647 -     * @return the return type
   1.648 -     */
   1.649 -    public Class<?> returnType() {
   1.650 -        return rtype;
   1.651 -    }
   1.652 -
   1.653 -    /**
   1.654 -     * Presents the parameter types as a list (a convenience method).
   1.655 -     * The list will be immutable.
   1.656 -     * @return the parameter types (as an immutable list)
   1.657 -     */
   1.658 -    public List<Class<?>> parameterList() {
   1.659 -        return Collections.unmodifiableList(Arrays.asList(ptypes));
   1.660 -    }
   1.661 -
   1.662 -    /*non-public*/ Class<?> lastParameterType() {
   1.663 -        int len = ptypes.length;
   1.664 -        return len == 0 ? void.class : ptypes[len-1];
   1.665 -    }
   1.666 -
   1.667 -    /**
   1.668 -     * Presents the parameter types as an array (a convenience method).
   1.669 -     * Changes to the array will not result in changes to the type.
   1.670 -     * @return the parameter types (as a fresh copy if necessary)
   1.671 -     */
   1.672 -    public Class<?>[] parameterArray() {
   1.673 -        return ptypes.clone();
   1.674 -    }
   1.675 -
   1.676 -    /**
   1.677 -     * Compares the specified object with this type for equality.
   1.678 -     * That is, it returns <tt>true</tt> if and only if the specified object
   1.679 -     * is also a method type with exactly the same parameters and return type.
   1.680 -     * @param x object to compare
   1.681 -     * @see Object#equals(Object)
   1.682 -     */
   1.683 -    @Override
   1.684 -    public boolean equals(Object x) {
   1.685 -        return this == x || x instanceof MethodType && equals((MethodType)x);
   1.686 -    }
   1.687 -
   1.688 -    private boolean equals(MethodType that) {
   1.689 -        return this.rtype == that.rtype
   1.690 -            && Arrays.equals(this.ptypes, that.ptypes);
   1.691 -    }
   1.692 -
   1.693 -    /**
   1.694 -     * Returns the hash code value for this method type.
   1.695 -     * It is defined to be the same as the hashcode of a List
   1.696 -     * whose elements are the return type followed by the
   1.697 -     * parameter types.
   1.698 -     * @return the hash code value for this method type
   1.699 -     * @see Object#hashCode()
   1.700 -     * @see #equals(Object)
   1.701 -     * @see List#hashCode()
   1.702 -     */
   1.703 -    @Override
   1.704 -    public int hashCode() {
   1.705 -      int hashCode = 31 + rtype.hashCode();
   1.706 -      for (Class<?> ptype : ptypes)
   1.707 -          hashCode = 31*hashCode + ptype.hashCode();
   1.708 -      return hashCode;
   1.709 -    }
   1.710 -
   1.711 -    /**
   1.712 -     * Returns a string representation of the method type,
   1.713 -     * of the form {@code "(PT0,PT1...)RT"}.
   1.714 -     * The string representation of a method type is a
   1.715 -     * parenthesis enclosed, comma separated list of type names,
   1.716 -     * followed immediately by the return type.
   1.717 -     * <p>
   1.718 -     * Each type is represented by its
   1.719 -     * {@link java.lang.Class#getSimpleName simple name}.
   1.720 -     */
   1.721 -    @Override
   1.722 -    public String toString() {
   1.723 -        StringBuilder sb = new StringBuilder();
   1.724 -        sb.append("(");
   1.725 -        for (int i = 0; i < ptypes.length; i++) {
   1.726 -            if (i > 0)  sb.append(",");
   1.727 -            sb.append(ptypes[i].getSimpleName());
   1.728 -        }
   1.729 -        sb.append(")");
   1.730 -        sb.append(rtype.getSimpleName());
   1.731 -        return sb.toString();
   1.732 -    }
   1.733 -
   1.734 -
   1.735 -    /*non-public*/
   1.736 -    boolean isViewableAs(MethodType newType) {
   1.737 -        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
   1.738 -            return false;
   1.739 -        int argc = parameterCount();
   1.740 -        if (argc != newType.parameterCount())
   1.741 -            return false;
   1.742 -        for (int i = 0; i < argc; i++) {
   1.743 -            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
   1.744 -                return false;
   1.745 -        }
   1.746 -        return true;
   1.747 -    }
   1.748 -    /*non-public*/
   1.749 -    boolean isCastableTo(MethodType newType) {
   1.750 -        int argc = parameterCount();
   1.751 -        if (argc != newType.parameterCount())
   1.752 -            return false;
   1.753 -        return true;
   1.754 -    }
   1.755 -    /*non-public*/
   1.756 -    boolean isConvertibleTo(MethodType newType) {
   1.757 -        if (!canConvert(returnType(), newType.returnType()))
   1.758 -            return false;
   1.759 -        int argc = parameterCount();
   1.760 -        if (argc != newType.parameterCount())
   1.761 -            return false;
   1.762 -        for (int i = 0; i < argc; i++) {
   1.763 -            if (!canConvert(newType.parameterType(i), parameterType(i)))
   1.764 -                return false;
   1.765 -        }
   1.766 -        return true;
   1.767 -    }
   1.768 -    /*non-public*/
   1.769 -    static boolean canConvert(Class<?> src, Class<?> dst) {
   1.770 -        // short-circuit a few cases:
   1.771 -        if (src == dst || dst == Object.class)  return true;
   1.772 -        // the remainder of this logic is documented in MethodHandle.asType
   1.773 -        if (src.isPrimitive()) {
   1.774 -            // can force void to an explicit null, a la reflect.Method.invoke
   1.775 -            // can also force void to a primitive zero, by analogy
   1.776 -            if (src == void.class)  return true;  //or !dst.isPrimitive()?
   1.777 -            Wrapper sw = Wrapper.forPrimitiveType(src);
   1.778 -            if (dst.isPrimitive()) {
   1.779 -                // P->P must widen
   1.780 -                return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
   1.781 -            } else {
   1.782 -                // P->R must box and widen
   1.783 -                return dst.isAssignableFrom(sw.wrapperType());
   1.784 -            }
   1.785 -        } else if (dst.isPrimitive()) {
   1.786 -            // any value can be dropped
   1.787 -            if (dst == void.class)  return true;
   1.788 -            Wrapper dw = Wrapper.forPrimitiveType(dst);
   1.789 -            // R->P must be able to unbox (from a dynamically chosen type) and widen
   1.790 -            // For example:
   1.791 -            //   Byte/Number/Comparable/Object -> dw:Byte -> byte.
   1.792 -            //   Character/Comparable/Object -> dw:Character -> char
   1.793 -            //   Boolean/Comparable/Object -> dw:Boolean -> boolean
   1.794 -            // This means that dw must be cast-compatible with src.
   1.795 -            if (src.isAssignableFrom(dw.wrapperType())) {
   1.796 -                return true;
   1.797 -            }
   1.798 -            // The above does not work if the source reference is strongly typed
   1.799 -            // to a wrapper whose primitive must be widened.  For example:
   1.800 -            //   Byte -> unbox:byte -> short/int/long/float/double
   1.801 -            //   Character -> unbox:char -> int/long/float/double
   1.802 -            if (Wrapper.isWrapperType(src) &&
   1.803 -                dw.isConvertibleFrom(Wrapper.forWrapperType(src))) {
   1.804 -                // can unbox from src and then widen to dst
   1.805 -                return true;
   1.806 -            }
   1.807 -            // We have already covered cases which arise due to runtime unboxing
   1.808 -            // of a reference type which covers several wrapper types:
   1.809 -            //   Object -> cast:Integer -> unbox:int -> long/float/double
   1.810 -            //   Serializable -> cast:Byte -> unbox:byte -> byte/short/int/long/float/double
   1.811 -            // An marginal case is Number -> dw:Character -> char, which would be OK if there were a
   1.812 -            // subclass of Number which wraps a value that can convert to char.
   1.813 -            // Since there is none, we don't need an extra check here to cover char or boolean.
   1.814 -            return false;
   1.815 -        } else {
   1.816 -            // R->R always works, since null is always valid dynamically
   1.817 -            return true;
   1.818 -        }
   1.819 -    }
   1.820 -
   1.821 -    /// Queries which have to do with the bytecode architecture
   1.822 -
   1.823 -    /** Reports the number of JVM stack slots required to invoke a method
   1.824 -     * of this type.  Note that (for historical reasons) the JVM requires
   1.825 -     * a second stack slot to pass long and double arguments.
   1.826 -     * So this method returns {@link #parameterCount() parameterCount} plus the
   1.827 -     * number of long and double parameters (if any).
   1.828 -     * <p>
   1.829 -     * This method is included for the benefit of applications that must
   1.830 -     * generate bytecodes that process method handles and invokedynamic.
   1.831 -     * @return the number of JVM stack slots for this type's parameters
   1.832 -     */
   1.833 -    /*non-public*/ int parameterSlotCount() {
   1.834 -        return form.parameterSlotCount();
   1.835 -    }
   1.836 -
   1.837 -    /*non-public*/ Invokers invokers() {
   1.838 -        Invokers inv = invokers;
   1.839 -        if (inv != null)  return inv;
   1.840 -        invokers = inv = new Invokers(this);
   1.841 -        return inv;
   1.842 -    }
   1.843 -
   1.844 -    /** Reports the number of JVM stack slots which carry all parameters including and after
   1.845 -     * the given position, which must be in the range of 0 to
   1.846 -     * {@code parameterCount} inclusive.  Successive parameters are
   1.847 -     * more shallowly stacked, and parameters are indexed in the bytecodes
   1.848 -     * according to their trailing edge.  Thus, to obtain the depth
   1.849 -     * in the outgoing call stack of parameter {@code N}, obtain
   1.850 -     * the {@code parameterSlotDepth} of its trailing edge
   1.851 -     * at position {@code N+1}.
   1.852 -     * <p>
   1.853 -     * Parameters of type {@code long} and {@code double} occupy
   1.854 -     * two stack slots (for historical reasons) and all others occupy one.
   1.855 -     * Therefore, the number returned is the number of arguments
   1.856 -     * <em>including</em> and <em>after</em> the given parameter,
   1.857 -     * <em>plus</em> the number of long or double arguments
   1.858 -     * at or after after the argument for the given parameter.
   1.859 -     * <p>
   1.860 -     * This method is included for the benefit of applications that must
   1.861 -     * generate bytecodes that process method handles and invokedynamic.
   1.862 -     * @param num an index (zero-based, inclusive) within the parameter types
   1.863 -     * @return the index of the (shallowest) JVM stack slot transmitting the
   1.864 -     *         given parameter
   1.865 -     * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
   1.866 -     */
   1.867 -    /*non-public*/ int parameterSlotDepth(int num) {
   1.868 -        if (num < 0 || num > ptypes.length)
   1.869 -            parameterType(num);  // force a range check
   1.870 -        return form.parameterToArgSlot(num-1);
   1.871 -    }
   1.872 -
   1.873 -    /** Reports the number of JVM stack slots required to receive a return value
   1.874 -     * from a method of this type.
   1.875 -     * If the {@link #returnType() return type} is void, it will be zero,
   1.876 -     * else if the return type is long or double, it will be two, else one.
   1.877 -     * <p>
   1.878 -     * This method is included for the benefit of applications that must
   1.879 -     * generate bytecodes that process method handles and invokedynamic.
   1.880 -     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
   1.881 -     * Will be removed for PFD.
   1.882 -     */
   1.883 -    /*non-public*/ int returnSlotCount() {
   1.884 -        return form.returnSlotCount();
   1.885 -    }
   1.886 -
   1.887 -    /**
   1.888 -     * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
   1.889 -     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
   1.890 -     * Any class or interface name embedded in the descriptor string
   1.891 -     * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
   1.892 -     * on the given loader (or if it is null, on the system class loader).
   1.893 -     * <p>
   1.894 -     * Note that it is possible to encounter method types which cannot be
   1.895 -     * constructed by this method, because their component types are
   1.896 -     * not all reachable from a common class loader.
   1.897 -     * <p>
   1.898 -     * This method is included for the benefit of applications that must
   1.899 -     * generate bytecodes that process method handles and {@code invokedynamic}.
   1.900 -     * @param descriptor a bytecode-level type descriptor string "(T...)T"
   1.901 -     * @param loader the class loader in which to look up the types
   1.902 -     * @return a method type matching the bytecode-level type descriptor
   1.903 -     * @throws NullPointerException if the string is null
   1.904 -     * @throws IllegalArgumentException if the string is not well-formed
   1.905 -     * @throws TypeNotPresentException if a named type cannot be found
   1.906 -     */
   1.907 -    public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
   1.908 -        throws IllegalArgumentException, TypeNotPresentException
   1.909 -    {
   1.910 -        if (!descriptor.startsWith("(") ||  // also generates NPE if needed
   1.911 -            descriptor.indexOf(')') < 0 ||
   1.912 -            descriptor.indexOf('.') >= 0)
   1.913 -            throw new IllegalArgumentException("not a method descriptor: "+descriptor);
   1.914 -        List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
   1.915 -        Class<?> rtype = types.remove(types.size() - 1);
   1.916 -        checkSlotCount(types.size());
   1.917 -        Class<?>[] ptypes = listToArray(types);
   1.918 -        return makeImpl(rtype, ptypes, true);
   1.919 -    }
   1.920 -
   1.921 -    /**
   1.922 -     * Produces a bytecode descriptor representation of the method type.
   1.923 -     * <p>
   1.924 -     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
   1.925 -     * Two distinct classes which share a common name but have different class loaders
   1.926 -     * will appear identical when viewed within descriptor strings.
   1.927 -     * <p>
   1.928 -     * This method is included for the benefit of applications that must
   1.929 -     * generate bytecodes that process method handles and {@code invokedynamic}.
   1.930 -     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
   1.931 -     * because the latter requires a suitable class loader argument.
   1.932 -     * @return the bytecode type descriptor representation
   1.933 -     */
   1.934 -    public String toMethodDescriptorString() {
   1.935 -        String desc = methodDescriptor;
   1.936 -        if (desc == null) {
   1.937 -            desc = BytecodeDescriptor.unparse(this);
   1.938 -            methodDescriptor = desc;
   1.939 -        }
   1.940 -        return desc;
   1.941 -    }
   1.942 -
   1.943 -    /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
   1.944 -        return BytecodeDescriptor.unparse(cls);
   1.945 -    }
   1.946 -
   1.947 -    /// Serialization.
   1.948 -
   1.949 -    /**
   1.950 -     * There are no serializable fields for {@code MethodType}.
   1.951 -     */
   1.952 -    private static final java.io.ObjectStreamField[] serialPersistentFields = { };
   1.953 -
   1.954 -//    /**
   1.955 -//     * Save the {@code MethodType} instance to a stream.
   1.956 -//     *
   1.957 -//     * @serialData
   1.958 -//     * For portability, the serialized format does not refer to named fields.
   1.959 -//     * Instead, the return type and parameter type arrays are written directly
   1.960 -//     * from the {@code writeObject} method, using two calls to {@code s.writeObject}
   1.961 -//     * as follows:
   1.962 -//     * <blockquote><pre>{@code
   1.963 -//s.writeObject(this.returnType());
   1.964 -//s.writeObject(this.parameterArray());
   1.965 -//     * }</pre></blockquote>
   1.966 -//     * <p>
   1.967 -//     * The deserialized field values are checked as if they were
   1.968 -//     * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
   1.969 -//     * For example, null values, or {@code void} parameter types,
   1.970 -//     * will lead to exceptions during deserialization.
   1.971 -//     * @param s the stream to write the object to
   1.972 -//     * @throws java.io.IOException if there is a problem writing the object
   1.973 -//     */
   1.974 -//    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
   1.975 -//        s.defaultWriteObject();  // requires serialPersistentFields to be an empty array
   1.976 -//        s.writeObject(returnType());
   1.977 -//        s.writeObject(parameterArray());
   1.978 -//    }
   1.979 -//
   1.980 -//    /**
   1.981 -//     * Reconstitute the {@code MethodType} instance from a stream (that is,
   1.982 -//     * deserialize it).
   1.983 -//     * This instance is a scratch object with bogus final fields.
   1.984 -//     * It provides the parameters to the factory method called by
   1.985 -//     * {@link #readResolve readResolve}.
   1.986 -//     * After that call it is discarded.
   1.987 -//     * @param s the stream to read the object from
   1.988 -//     * @throws java.io.IOException if there is a problem reading the object
   1.989 -//     * @throws ClassNotFoundException if one of the component classes cannot be resolved
   1.990 -//     * @see #MethodType()
   1.991 -//     * @see #readResolve
   1.992 -//     * @see #writeObject
   1.993 -//     */
   1.994 -//    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
   1.995 -//        s.defaultReadObject();  // requires serialPersistentFields to be an empty array
   1.996 -//
   1.997 -//        Class<?>   returnType     = (Class<?>)   s.readObject();
   1.998 -//        Class<?>[] parameterArray = (Class<?>[]) s.readObject();
   1.999 -//
  1.1000 -//        // Probably this object will never escape, but let's check
  1.1001 -//        // the field values now, just to be sure.
  1.1002 -//        checkRtype(returnType);
  1.1003 -//        checkPtypes(parameterArray);
  1.1004 -//
  1.1005 -//        parameterArray = parameterArray.clone();  // make sure it is unshared
  1.1006 -//        MethodType_init(returnType, parameterArray);
  1.1007 -//    }
  1.1008 -
  1.1009 -    /**
  1.1010 -     * For serialization only.
  1.1011 -     * Sets the final fields to null, pending {@code Unsafe.putObject}.
  1.1012 -     */
  1.1013 -    private MethodType() {
  1.1014 -        this.rtype = null;
  1.1015 -        this.ptypes = null;
  1.1016 -    }
  1.1017 -//    private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
  1.1018 -//        // In order to communicate these values to readResolve, we must
  1.1019 -//        // store them into the implementation-specific final fields.
  1.1020 -//        checkRtype(rtype);
  1.1021 -//        checkPtypes(ptypes);
  1.1022 -//        UNSAFE.putObject(this, rtypeOffset, rtype);
  1.1023 -//        UNSAFE.putObject(this, ptypesOffset, ptypes);
  1.1024 -//    }
  1.1025 -
  1.1026 -    // Support for resetting final fields while deserializing
  1.1027 -//    private static final long rtypeOffset, ptypesOffset;
  1.1028 -//    static {
  1.1029 -//        try {
  1.1030 -//            rtypeOffset = UNSAFE.objectFieldOffset
  1.1031 -//                (MethodType.class.getDeclaredField("rtype"));
  1.1032 -//            ptypesOffset = UNSAFE.objectFieldOffset
  1.1033 -//                (MethodType.class.getDeclaredField("ptypes"));
  1.1034 -//        } catch (Exception ex) {
  1.1035 -//            throw new Error(ex);
  1.1036 -//        }
  1.1037 -//    }
  1.1038 -
  1.1039 -    /**
  1.1040 -     * Resolves and initializes a {@code MethodType} object
  1.1041 -     * after serialization.
  1.1042 -     * @return the fully initialized {@code MethodType} object
  1.1043 -     */
  1.1044 -    private Object readResolve() {
  1.1045 -        // Do not use a trusted path for deserialization:
  1.1046 -        //return makeImpl(rtype, ptypes, true);
  1.1047 -        // Verify all operands, and make sure ptypes is unshared:
  1.1048 -        return methodType(rtype, ptypes);
  1.1049 -    }
  1.1050 -
  1.1051 -    /**
  1.1052 -     * Simple implementation of weak concurrent intern set.
  1.1053 -     *
  1.1054 -     * @param <T> interned type
  1.1055 -     */
  1.1056 -    private static class ConcurrentWeakInternSet<T> {
  1.1057 -
  1.1058 -        private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
  1.1059 -        private final ReferenceQueue<T> stale;
  1.1060 -
  1.1061 -        public ConcurrentWeakInternSet() {
  1.1062 -            this.map = new ConcurrentHashMap<>();
  1.1063 -            this.stale = new ReferenceQueue<>();
  1.1064 -        }
  1.1065 -
  1.1066 -        /**
  1.1067 -         * Get the existing interned element.
  1.1068 -         * This method returns null if no element is interned.
  1.1069 -         *
  1.1070 -         * @param elem element to look up
  1.1071 -         * @return the interned element
  1.1072 -         */
  1.1073 -        public T get(T elem) {
  1.1074 -            if (elem == null) throw new NullPointerException();
  1.1075 -            expungeStaleElements();
  1.1076 -
  1.1077 -            WeakEntry<T> value = map.get(new WeakEntry<>(elem));
  1.1078 -            if (value != null) {
  1.1079 -                T res = value.get();
  1.1080 -                if (res != null) {
  1.1081 -                    return res;
  1.1082 -                }
  1.1083 -            }
  1.1084 -            return null;
  1.1085 -        }
  1.1086 -
  1.1087 -        /**
  1.1088 -         * Interns the element.
  1.1089 -         * Always returns non-null element, matching the one in the intern set.
  1.1090 -         * Under the race against another add(), it can return <i>different</i>
  1.1091 -         * element, if another thread beats us to interning it.
  1.1092 -         *
  1.1093 -         * @param elem element to add
  1.1094 -         * @return element that was actually added
  1.1095 -         */
  1.1096 -        public T add(T elem) {
  1.1097 -            if (elem == null) throw new NullPointerException();
  1.1098 -
  1.1099 -            // Playing double race here, and so spinloop is required.
  1.1100 -            // First race is with two concurrent updaters.
  1.1101 -            // Second race is with GC purging weak ref under our feet.
  1.1102 -            // Hopefully, we almost always end up with a single pass.
  1.1103 -            T interned;
  1.1104 -            WeakEntry<T> e = new WeakEntry<>(elem, stale);
  1.1105 -            do {
  1.1106 -                expungeStaleElements();
  1.1107 -                WeakEntry<T> exist = map.putIfAbsent(e, e);
  1.1108 -                interned = (exist == null) ? elem : exist.get();
  1.1109 -            } while (interned == null);
  1.1110 -            return interned;
  1.1111 -        }
  1.1112 -
  1.1113 -        private void expungeStaleElements() {
  1.1114 -            Reference<? extends T> reference;
  1.1115 -            while ((reference = stale.poll()) != null) {
  1.1116 -                map.remove(reference);
  1.1117 -            }
  1.1118 -        }
  1.1119 -
  1.1120 -        private static class WeakEntry<T> extends WeakReference<T> {
  1.1121 -
  1.1122 -            public final int hashcode;
  1.1123 -
  1.1124 -            public WeakEntry(T key, ReferenceQueue<T> queue) {
  1.1125 -                super(key, queue);
  1.1126 -                hashcode = key.hashCode();
  1.1127 -            }
  1.1128 -
  1.1129 -            public WeakEntry(T key) {
  1.1130 -                super(key);
  1.1131 -                hashcode = key.hashCode();
  1.1132 -            }
  1.1133 -
  1.1134 -            @Override
  1.1135 -            public boolean equals(Object obj) {
  1.1136 -                if (obj instanceof WeakEntry) {
  1.1137 -                    Object that = ((WeakEntry) obj).get();
  1.1138 -                    Object mine = get();
  1.1139 -                    return (that == null || mine == null) ? (this == obj) : mine.equals(that);
  1.1140 -                }
  1.1141 -                return false;
  1.1142 -            }
  1.1143 -
  1.1144 -            @Override
  1.1145 -            public int hashCode() {
  1.1146 -                return hashcode;
  1.1147 -            }
  1.1148 -
  1.1149 -        }
  1.1150 -    }
  1.1151 -
  1.1152 -}