rt/emul/compact/src/main/java/sun/invoke/util/ValueConversions.java
branchjdk8
changeset 1675 cd50c1894ce5
parent 1674 eca8e9c3ec3e
child 1678 35daab73e225
     1.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/ValueConversions.java	Sun Aug 17 20:09:05 2014 +0200
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1188 +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 sun.invoke.util;
    1.30 -
    1.31 -import java.lang.invoke.MethodHandle;
    1.32 -import java.lang.invoke.MethodHandles;
    1.33 -import java.lang.invoke.MethodHandles.Lookup;
    1.34 -import java.lang.invoke.MethodType;
    1.35 -import java.security.AccessController;
    1.36 -import java.security.PrivilegedAction;
    1.37 -import java.util.ArrayList;
    1.38 -import java.util.Arrays;
    1.39 -import java.util.Collections;
    1.40 -import java.util.EnumMap;
    1.41 -import java.util.List;
    1.42 -
    1.43 -public class ValueConversions {
    1.44 -    private static final Class<?> THIS_CLASS = ValueConversions.class;
    1.45 -    // Do not adjust this except for special platforms:
    1.46 -    private static final int MAX_ARITY;
    1.47 -    static {
    1.48 -        final Object[] values = { 255 };
    1.49 -        AccessController.doPrivileged(new PrivilegedAction<Void>() {
    1.50 -                @Override
    1.51 -                public Void run() {
    1.52 -                    values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
    1.53 -                    return null;
    1.54 -                }
    1.55 -            });
    1.56 -        MAX_ARITY = (Integer) values[0];
    1.57 -    }
    1.58 -
    1.59 -    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
    1.60 -
    1.61 -    private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
    1.62 -        @SuppressWarnings("unchecked")  // generic array creation
    1.63 -        EnumMap<Wrapper, MethodHandle>[] caches
    1.64 -                = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap<?,?>[n];
    1.65 -        for (int i = 0; i < n; i++)
    1.66 -            caches[i] = new EnumMap<>(Wrapper.class);
    1.67 -        return caches;
    1.68 -    }
    1.69 -
    1.70 -    /// Converting references to values.
    1.71 -
    1.72 -    // There are several levels of this unboxing conversions:
    1.73 -    //   no conversions:  exactly Integer.valueOf, etc.
    1.74 -    //   implicit conversions sanctioned by JLS 5.1.2, etc.
    1.75 -    //   explicit conversions as allowed by explicitCastArguments
    1.76 -
    1.77 -    static int unboxInteger(Object x, boolean cast) {
    1.78 -        if (x instanceof Integer)
    1.79 -            return ((Integer) x).intValue();
    1.80 -        return primitiveConversion(Wrapper.INT, x, cast).intValue();
    1.81 -    }
    1.82 -
    1.83 -    static byte unboxByte(Object x, boolean cast) {
    1.84 -        if (x instanceof Byte)
    1.85 -            return ((Byte) x).byteValue();
    1.86 -        return primitiveConversion(Wrapper.BYTE, x, cast).byteValue();
    1.87 -    }
    1.88 -
    1.89 -    static short unboxShort(Object x, boolean cast) {
    1.90 -        if (x instanceof Short)
    1.91 -            return ((Short) x).shortValue();
    1.92 -        return primitiveConversion(Wrapper.SHORT, x, cast).shortValue();
    1.93 -    }
    1.94 -
    1.95 -    static boolean unboxBoolean(Object x, boolean cast) {
    1.96 -        if (x instanceof Boolean)
    1.97 -            return ((Boolean) x).booleanValue();
    1.98 -        return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0;
    1.99 -    }
   1.100 -
   1.101 -    static char unboxCharacter(Object x, boolean cast) {
   1.102 -        if (x instanceof Character)
   1.103 -            return ((Character) x).charValue();
   1.104 -        return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue();
   1.105 -    }
   1.106 -
   1.107 -    static long unboxLong(Object x, boolean cast) {
   1.108 -        if (x instanceof Long)
   1.109 -            return ((Long) x).longValue();
   1.110 -        return primitiveConversion(Wrapper.LONG, x, cast).longValue();
   1.111 -    }
   1.112 -
   1.113 -    static float unboxFloat(Object x, boolean cast) {
   1.114 -        if (x instanceof Float)
   1.115 -            return ((Float) x).floatValue();
   1.116 -        return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue();
   1.117 -    }
   1.118 -
   1.119 -    static double unboxDouble(Object x, boolean cast) {
   1.120 -        if (x instanceof Double)
   1.121 -            return ((Double) x).doubleValue();
   1.122 -        return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
   1.123 -    }
   1.124 -
   1.125 -    private static MethodType unboxType(Wrapper wrap) {
   1.126 -        return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
   1.127 -    }
   1.128 -
   1.129 -    private static final EnumMap<Wrapper, MethodHandle>[]
   1.130 -            UNBOX_CONVERSIONS = newWrapperCaches(2);
   1.131 -
   1.132 -    private static MethodHandle unbox(Wrapper wrap, boolean cast) {
   1.133 -        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)];
   1.134 -        MethodHandle mh = cache.get(wrap);
   1.135 -        if (mh != null) {
   1.136 -            return mh;
   1.137 -        }
   1.138 -        // slow path
   1.139 -        switch (wrap) {
   1.140 -            case OBJECT:
   1.141 -                mh = IDENTITY; break;
   1.142 -            case VOID:
   1.143 -                mh = IGNORE; break;
   1.144 -        }
   1.145 -        if (mh != null) {
   1.146 -            cache.put(wrap, mh);
   1.147 -            return mh;
   1.148 -        }
   1.149 -        // look up the method
   1.150 -        String name = "unbox" + wrap.wrapperSimpleName();
   1.151 -        MethodType type = unboxType(wrap);
   1.152 -        try {
   1.153 -            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
   1.154 -        } catch (ReflectiveOperationException ex) {
   1.155 -            mh = null;
   1.156 -        }
   1.157 -        if (mh != null) {
   1.158 -            mh = MethodHandles.insertArguments(mh, 1, cast);
   1.159 -            cache.put(wrap, mh);
   1.160 -            return mh;
   1.161 -        }
   1.162 -        throw new IllegalArgumentException("cannot find unbox adapter for " + wrap
   1.163 -                + (cast ? " (cast)" : ""));
   1.164 -    }
   1.165 -
   1.166 -    public static MethodHandle unboxCast(Wrapper type) {
   1.167 -        return unbox(type, true);
   1.168 -    }
   1.169 -
   1.170 -    public static MethodHandle unbox(Class<?> type) {
   1.171 -        return unbox(Wrapper.forPrimitiveType(type), false);
   1.172 -    }
   1.173 -
   1.174 -    public static MethodHandle unboxCast(Class<?> type) {
   1.175 -        return unbox(Wrapper.forPrimitiveType(type), true);
   1.176 -    }
   1.177 -
   1.178 -    static private final Integer ZERO_INT = 0, ONE_INT = 1;
   1.179 -
   1.180 -    /// Primitive conversions
   1.181 -    /**
   1.182 -     * Produce a Number which represents the given value {@code x}
   1.183 -     * according to the primitive type of the given wrapper {@code wrap}.
   1.184 -     * Caller must invoke intValue, byteValue, longValue (etc.) on the result
   1.185 -     * to retrieve the desired primitive value.
   1.186 -     */
   1.187 -    public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
   1.188 -        // Maybe merge this code with Wrapper.convert/cast.
   1.189 -        Number res;
   1.190 -        if (x == null) {
   1.191 -            if (!cast)  return null;
   1.192 -            return ZERO_INT;
   1.193 -        }
   1.194 -        if (x instanceof Number) {
   1.195 -            res = (Number) x;
   1.196 -        } else if (x instanceof Boolean) {
   1.197 -            res = ((boolean)x ? ONE_INT : ZERO_INT);
   1.198 -        } else if (x instanceof Character) {
   1.199 -            res = (int)(char)x;
   1.200 -        } else {
   1.201 -            // this will fail with the required ClassCastException:
   1.202 -            res = (Number) x;
   1.203 -        }
   1.204 -        Wrapper xwrap = Wrapper.findWrapperType(x.getClass());
   1.205 -        if (xwrap == null || !cast && !wrap.isConvertibleFrom(xwrap))
   1.206 -            // this will fail with the required ClassCastException:
   1.207 -            return (Number) wrap.wrapperType().cast(x);
   1.208 -        return res;
   1.209 -    }
   1.210 -
   1.211 -    /**
   1.212 -     * The JVM verifier allows boolean, byte, short, or char to widen to int.
   1.213 -     * Support exactly this conversion, from a boxed value type Boolean,
   1.214 -     * Byte, Short, Character, or Integer.
   1.215 -     */
   1.216 -    public static int widenSubword(Object x) {
   1.217 -        if (x instanceof Integer)
   1.218 -            return (int) x;
   1.219 -        else if (x instanceof Boolean)
   1.220 -            return fromBoolean((boolean) x);
   1.221 -        else if (x instanceof Character)
   1.222 -            return (char) x;
   1.223 -        else if (x instanceof Short)
   1.224 -            return (short) x;
   1.225 -        else if (x instanceof Byte)
   1.226 -            return (byte) x;
   1.227 -        else
   1.228 -            // Fail with a ClassCastException.
   1.229 -            return (int) x;
   1.230 -    }
   1.231 -
   1.232 -    /// Converting primitives to references
   1.233 -
   1.234 -    static Integer boxInteger(int x) {
   1.235 -        return x;
   1.236 -    }
   1.237 -
   1.238 -    static Byte boxByte(byte x) {
   1.239 -        return x;
   1.240 -    }
   1.241 -
   1.242 -    static Short boxShort(short x) {
   1.243 -        return x;
   1.244 -    }
   1.245 -
   1.246 -    static Boolean boxBoolean(boolean x) {
   1.247 -        return x;
   1.248 -    }
   1.249 -
   1.250 -    static Character boxCharacter(char x) {
   1.251 -        return x;
   1.252 -    }
   1.253 -
   1.254 -    static Long boxLong(long x) {
   1.255 -        return x;
   1.256 -    }
   1.257 -
   1.258 -    static Float boxFloat(float x) {
   1.259 -        return x;
   1.260 -    }
   1.261 -
   1.262 -    static Double boxDouble(double x) {
   1.263 -        return x;
   1.264 -    }
   1.265 -
   1.266 -    private static MethodType boxType(Wrapper wrap) {
   1.267 -        // be exact, since return casts are hard to compose
   1.268 -        Class<?> boxType = wrap.wrapperType();
   1.269 -        return MethodType.methodType(boxType, wrap.primitiveType());
   1.270 -    }
   1.271 -
   1.272 -    private static final EnumMap<Wrapper, MethodHandle>[]
   1.273 -            BOX_CONVERSIONS = newWrapperCaches(2);
   1.274 -
   1.275 -    private static MethodHandle box(Wrapper wrap, boolean exact) {
   1.276 -        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)];
   1.277 -        MethodHandle mh = cache.get(wrap);
   1.278 -        if (mh != null) {
   1.279 -            return mh;
   1.280 -        }
   1.281 -        // slow path
   1.282 -        switch (wrap) {
   1.283 -            case OBJECT:
   1.284 -                mh = IDENTITY; break;
   1.285 -            case VOID:
   1.286 -                mh = ZERO_OBJECT;
   1.287 -                break;
   1.288 -        }
   1.289 -        if (mh != null) {
   1.290 -            cache.put(wrap, mh);
   1.291 -            return mh;
   1.292 -        }
   1.293 -        // look up the method
   1.294 -        String name = "box" + wrap.wrapperSimpleName();
   1.295 -        MethodType type = boxType(wrap);
   1.296 -        if (exact) {
   1.297 -            try {
   1.298 -                mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
   1.299 -            } catch (ReflectiveOperationException ex) {
   1.300 -                mh = null;
   1.301 -            }
   1.302 -        } else {
   1.303 -            mh = box(wrap, !exact).asType(type.erase());
   1.304 -        }
   1.305 -        if (mh != null) {
   1.306 -            cache.put(wrap, mh);
   1.307 -            return mh;
   1.308 -        }
   1.309 -        throw new IllegalArgumentException("cannot find box adapter for "
   1.310 -                + wrap + (exact ? " (exact)" : ""));
   1.311 -    }
   1.312 -
   1.313 -    public static MethodHandle box(Class<?> type) {
   1.314 -        boolean exact = false;
   1.315 -        // e.g., boxShort(short)Short if exact,
   1.316 -        // e.g., boxShort(short)Object if !exact
   1.317 -        return box(Wrapper.forPrimitiveType(type), exact);
   1.318 -    }
   1.319 -
   1.320 -    public static MethodHandle box(Wrapper type) {
   1.321 -        boolean exact = false;
   1.322 -        return box(type, exact);
   1.323 -    }
   1.324 -
   1.325 -    /// Constant functions
   1.326 -
   1.327 -    static void ignore(Object x) {
   1.328 -        // no value to return; this is an unbox of null
   1.329 -    }
   1.330 -
   1.331 -    static void empty() {
   1.332 -    }
   1.333 -
   1.334 -    static Object zeroObject() {
   1.335 -        return null;
   1.336 -    }
   1.337 -
   1.338 -    static int zeroInteger() {
   1.339 -        return 0;
   1.340 -    }
   1.341 -
   1.342 -    static long zeroLong() {
   1.343 -        return 0;
   1.344 -    }
   1.345 -
   1.346 -    static float zeroFloat() {
   1.347 -        return 0;
   1.348 -    }
   1.349 -
   1.350 -    static double zeroDouble() {
   1.351 -        return 0;
   1.352 -    }
   1.353 -
   1.354 -    private static final EnumMap<Wrapper, MethodHandle>[]
   1.355 -            CONSTANT_FUNCTIONS = newWrapperCaches(2);
   1.356 -
   1.357 -    public static MethodHandle zeroConstantFunction(Wrapper wrap) {
   1.358 -        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
   1.359 -        MethodHandle mh = cache.get(wrap);
   1.360 -        if (mh != null) {
   1.361 -            return mh;
   1.362 -        }
   1.363 -        // slow path
   1.364 -        MethodType type = MethodType.methodType(wrap.primitiveType());
   1.365 -        switch (wrap) {
   1.366 -            case VOID:
   1.367 -                mh = EMPTY;
   1.368 -                break;
   1.369 -            case OBJECT:
   1.370 -            case INT: case LONG: case FLOAT: case DOUBLE:
   1.371 -                try {
   1.372 -                    mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
   1.373 -                } catch (ReflectiveOperationException ex) {
   1.374 -                    mh = null;
   1.375 -                }
   1.376 -                break;
   1.377 -        }
   1.378 -        if (mh != null) {
   1.379 -            cache.put(wrap, mh);
   1.380 -            return mh;
   1.381 -        }
   1.382 -
   1.383 -        // use zeroInt and cast the result
   1.384 -        if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
   1.385 -            mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
   1.386 -            cache.put(wrap, mh);
   1.387 -            return mh;
   1.388 -        }
   1.389 -        throw new IllegalArgumentException("cannot find zero constant for " + wrap);
   1.390 -    }
   1.391 -
   1.392 -    /// Converting references to references.
   1.393 -
   1.394 -    /**
   1.395 -     * Identity function.
   1.396 -     * @param x an arbitrary reference value
   1.397 -     * @return the same value x
   1.398 -     */
   1.399 -    static <T> T identity(T x) {
   1.400 -        return x;
   1.401 -    }
   1.402 -
   1.403 -    static <T> T[] identity(T[] x) {
   1.404 -        return x;
   1.405 -    }
   1.406 -
   1.407 -    /**
   1.408 -     * Identity function on ints.
   1.409 -     * @param x an arbitrary int value
   1.410 -     * @return the same value x
   1.411 -     */
   1.412 -    static int identity(int x) {
   1.413 -        return x;
   1.414 -    }
   1.415 -
   1.416 -    static byte identity(byte x) {
   1.417 -        return x;
   1.418 -    }
   1.419 -
   1.420 -    static short identity(short x) {
   1.421 -        return x;
   1.422 -    }
   1.423 -
   1.424 -    static boolean identity(boolean x) {
   1.425 -        return x;
   1.426 -    }
   1.427 -
   1.428 -    static char identity(char x) {
   1.429 -        return x;
   1.430 -    }
   1.431 -
   1.432 -    /**
   1.433 -     * Identity function on longs.
   1.434 -     * @param x an arbitrary long value
   1.435 -     * @return the same value x
   1.436 -     */
   1.437 -    static long identity(long x) {
   1.438 -        return x;
   1.439 -    }
   1.440 -
   1.441 -    static float identity(float x) {
   1.442 -        return x;
   1.443 -    }
   1.444 -
   1.445 -    static double identity(double x) {
   1.446 -        return x;
   1.447 -    }
   1.448 -
   1.449 -    /**
   1.450 -     * Identity function, with reference cast.
   1.451 -     * @param t an arbitrary reference type
   1.452 -     * @param x an arbitrary reference value
   1.453 -     * @return the same value x
   1.454 -     */
   1.455 -    @SuppressWarnings("unchecked")
   1.456 -    static <T,U> T castReference(Class<? extends T> t, U x) {
   1.457 -        // inlined Class.cast because we can't ForceInline it
   1.458 -        if (x != null && !t.isInstance(x))
   1.459 -            throw newClassCastException(t, x);
   1.460 -        return (T) x;
   1.461 -    }
   1.462 -
   1.463 -    private static ClassCastException newClassCastException(Class<?> t, Object obj) {
   1.464 -        return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
   1.465 -    }
   1.466 -
   1.467 -    private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
   1.468 -            ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
   1.469 -    static {
   1.470 -        try {
   1.471 -            MethodType idType = MethodType.genericMethodType(1);
   1.472 -            MethodType castType = idType.insertParameterTypes(0, Class.class);
   1.473 -            MethodType ignoreType = idType.changeReturnType(void.class);
   1.474 -            MethodType zeroObjectType = MethodType.genericMethodType(0);
   1.475 -            IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
   1.476 -            //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
   1.477 -            CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
   1.478 -            ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
   1.479 -            IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
   1.480 -            EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
   1.481 -            ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
   1.482 -            FILL_NEW_ARRAY = IMPL_LOOKUP
   1.483 -                    .findStatic(THIS_CLASS, "fillNewArray",
   1.484 -                          MethodType.methodType(Object[].class, Integer.class, Object[].class));
   1.485 -            FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
   1.486 -                    .findStatic(THIS_CLASS, "fillNewTypedArray",
   1.487 -                          MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
   1.488 -        } catch (NoSuchMethodException | IllegalAccessException ex) {
   1.489 -            throw newInternalError("uncaught exception", ex);
   1.490 -        }
   1.491 -    }
   1.492 -
   1.493 -    // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
   1.494 -    static class LazyStatics {
   1.495 -        private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
   1.496 -        static {
   1.497 -            try {
   1.498 -                //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
   1.499 -                COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
   1.500 -                COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
   1.501 -                MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
   1.502 -            } catch (ReflectiveOperationException ex) {
   1.503 -                throw newInternalError("uncaught exception", ex);
   1.504 -            }
   1.505 -        }
   1.506 -    }
   1.507 -
   1.508 -    private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
   1.509 -            = newWrapperCaches(1);
   1.510 -
   1.511 -    /** Return a method that casts its sole argument (an Object) to the given type
   1.512 -     *  and returns it as the given type.
   1.513 -     */
   1.514 -    public static MethodHandle cast(Class<?> type) {
   1.515 -        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
   1.516 -        MethodHandle mh;
   1.517 -        Wrapper wrap = null;
   1.518 -        EnumMap<Wrapper, MethodHandle> cache = null;
   1.519 -        if (Wrapper.isWrapperType(type)) {
   1.520 -            wrap = Wrapper.forWrapperType(type);
   1.521 -            cache = WRAPPER_CASTS[0];
   1.522 -            mh = cache.get(wrap);
   1.523 -            if (mh != null)  return mh;
   1.524 -        }
   1.525 -        mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
   1.526 -        if (cache != null)
   1.527 -            cache.put(wrap, mh);
   1.528 -        return mh;
   1.529 -    }
   1.530 -
   1.531 -    public static MethodHandle identity() {
   1.532 -        return IDENTITY;
   1.533 -    }
   1.534 -
   1.535 -    public static MethodHandle identity(Class<?> type) {
   1.536 -        if (!type.isPrimitive())
   1.537 -            // Reference identity has been moved into MethodHandles:
   1.538 -            return MethodHandles.identity(type);
   1.539 -        return identity(Wrapper.findPrimitiveType(type));
   1.540 -    }
   1.541 -
   1.542 -    public static MethodHandle identity(Wrapper wrap) {
   1.543 -        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
   1.544 -        MethodHandle mh = cache.get(wrap);
   1.545 -        if (mh != null) {
   1.546 -            return mh;
   1.547 -        }
   1.548 -        // slow path
   1.549 -        MethodType type = MethodType.methodType(wrap.primitiveType());
   1.550 -        if (wrap != Wrapper.VOID)
   1.551 -            type = type.appendParameterTypes(wrap.primitiveType());
   1.552 -        try {
   1.553 -            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
   1.554 -        } catch (ReflectiveOperationException ex) {
   1.555 -            mh = null;
   1.556 -        }
   1.557 -        if (mh == null && wrap == Wrapper.VOID) {
   1.558 -            mh = EMPTY;  // #(){} : #()void
   1.559 -        }
   1.560 -        if (mh != null) {
   1.561 -            cache.put(wrap, mh);
   1.562 -            return mh;
   1.563 -        }
   1.564 -
   1.565 -        if (mh != null) {
   1.566 -            cache.put(wrap, mh);
   1.567 -            return mh;
   1.568 -        }
   1.569 -        throw new IllegalArgumentException("cannot find identity for " + wrap);
   1.570 -    }
   1.571 -
   1.572 -    /// Primitive conversions.
   1.573 -    // These are supported directly by the JVM, usually by a single instruction.
   1.574 -    // In the case of narrowing to a subword, there may be a pair of instructions.
   1.575 -    // In the case of booleans, there may be a helper routine to manage a 1-bit value.
   1.576 -    // This is the full 8x8 matrix (minus the diagonal).
   1.577 -
   1.578 -    // narrow double to all other types:
   1.579 -    static float doubleToFloat(double x) {  // bytecode: d2f
   1.580 -        return (float) x;
   1.581 -    }
   1.582 -    static long doubleToLong(double x) {  // bytecode: d2l
   1.583 -        return (long) x;
   1.584 -    }
   1.585 -    static int doubleToInt(double x) {  // bytecode: d2i
   1.586 -        return (int) x;
   1.587 -    }
   1.588 -    static short doubleToShort(double x) {  // bytecodes: d2i, i2s
   1.589 -        return (short) x;
   1.590 -    }
   1.591 -    static char doubleToChar(double x) {  // bytecodes: d2i, i2c
   1.592 -        return (char) x;
   1.593 -    }
   1.594 -    static byte doubleToByte(double x) {  // bytecodes: d2i, i2b
   1.595 -        return (byte) x;
   1.596 -    }
   1.597 -    static boolean doubleToBoolean(double x) {
   1.598 -        return toBoolean((byte) x);
   1.599 -    }
   1.600 -
   1.601 -    // widen float:
   1.602 -    static double floatToDouble(float x) {  // bytecode: f2d
   1.603 -        return x;
   1.604 -    }
   1.605 -    // narrow float:
   1.606 -    static long floatToLong(float x) {  // bytecode: f2l
   1.607 -        return (long) x;
   1.608 -    }
   1.609 -    static int floatToInt(float x) {  // bytecode: f2i
   1.610 -        return (int) x;
   1.611 -    }
   1.612 -    static short floatToShort(float x) {  // bytecodes: f2i, i2s
   1.613 -        return (short) x;
   1.614 -    }
   1.615 -    static char floatToChar(float x) {  // bytecodes: f2i, i2c
   1.616 -        return (char) x;
   1.617 -    }
   1.618 -    static byte floatToByte(float x) {  // bytecodes: f2i, i2b
   1.619 -        return (byte) x;
   1.620 -    }
   1.621 -    static boolean floatToBoolean(float x) {
   1.622 -        return toBoolean((byte) x);
   1.623 -    }
   1.624 -
   1.625 -    // widen long:
   1.626 -    static double longToDouble(long x) {  // bytecode: l2d
   1.627 -        return x;
   1.628 -    }
   1.629 -    static float longToFloat(long x) {  // bytecode: l2f
   1.630 -        return x;
   1.631 -    }
   1.632 -    // narrow long:
   1.633 -    static int longToInt(long x) {  // bytecode: l2i
   1.634 -        return (int) x;
   1.635 -    }
   1.636 -    static short longToShort(long x) {  // bytecodes: f2i, i2s
   1.637 -        return (short) x;
   1.638 -    }
   1.639 -    static char longToChar(long x) {  // bytecodes: f2i, i2c
   1.640 -        return (char) x;
   1.641 -    }
   1.642 -    static byte longToByte(long x) {  // bytecodes: f2i, i2b
   1.643 -        return (byte) x;
   1.644 -    }
   1.645 -    static boolean longToBoolean(long x) {
   1.646 -        return toBoolean((byte) x);
   1.647 -    }
   1.648 -
   1.649 -    // widen int:
   1.650 -    static double intToDouble(int x) {  // bytecode: i2d
   1.651 -        return x;
   1.652 -    }
   1.653 -    static float intToFloat(int x) {  // bytecode: i2f
   1.654 -        return x;
   1.655 -    }
   1.656 -    static long intToLong(int x) {  // bytecode: i2l
   1.657 -        return x;
   1.658 -    }
   1.659 -    // narrow int:
   1.660 -    static short intToShort(int x) {  // bytecode: i2s
   1.661 -        return (short) x;
   1.662 -    }
   1.663 -    static char intToChar(int x) {  // bytecode: i2c
   1.664 -        return (char) x;
   1.665 -    }
   1.666 -    static byte intToByte(int x) {  // bytecode: i2b
   1.667 -        return (byte) x;
   1.668 -    }
   1.669 -    static boolean intToBoolean(int x) {
   1.670 -        return toBoolean((byte) x);
   1.671 -    }
   1.672 -
   1.673 -    // widen short:
   1.674 -    static double shortToDouble(short x) {  // bytecode: i2d (implicit 's2i')
   1.675 -        return x;
   1.676 -    }
   1.677 -    static float shortToFloat(short x) {  // bytecode: i2f (implicit 's2i')
   1.678 -        return x;
   1.679 -    }
   1.680 -    static long shortToLong(short x) {  // bytecode: i2l (implicit 's2i')
   1.681 -        return x;
   1.682 -    }
   1.683 -    static int shortToInt(short x) {  // (implicit 's2i')
   1.684 -        return x;
   1.685 -    }
   1.686 -    // narrow short:
   1.687 -    static char shortToChar(short x) {  // bytecode: i2c (implicit 's2i')
   1.688 -        return (char)x;
   1.689 -    }
   1.690 -    static byte shortToByte(short x) {  // bytecode: i2b (implicit 's2i')
   1.691 -        return (byte)x;
   1.692 -    }
   1.693 -    static boolean shortToBoolean(short x) {
   1.694 -        return toBoolean((byte) x);
   1.695 -    }
   1.696 -
   1.697 -    // widen char:
   1.698 -    static double charToDouble(char x) {  // bytecode: i2d (implicit 'c2i')
   1.699 -        return x;
   1.700 -    }
   1.701 -    static float charToFloat(char x) {  // bytecode: i2f (implicit 'c2i')
   1.702 -        return x;
   1.703 -    }
   1.704 -    static long charToLong(char x) {  // bytecode: i2l (implicit 'c2i')
   1.705 -        return x;
   1.706 -    }
   1.707 -    static int charToInt(char x) {  // (implicit 'c2i')
   1.708 -        return x;
   1.709 -    }
   1.710 -    // narrow char:
   1.711 -    static short charToShort(char x) {  // bytecode: i2s (implicit 'c2i')
   1.712 -        return (short)x;
   1.713 -    }
   1.714 -    static byte charToByte(char x) {  // bytecode: i2b (implicit 'c2i')
   1.715 -        return (byte)x;
   1.716 -    }
   1.717 -    static boolean charToBoolean(char x) {
   1.718 -        return toBoolean((byte) x);
   1.719 -    }
   1.720 -
   1.721 -    // widen byte:
   1.722 -    static double byteToDouble(byte x) {  // bytecode: i2d (implicit 'b2i')
   1.723 -        return x;
   1.724 -    }
   1.725 -    static float byteToFloat(byte x) {  // bytecode: i2f (implicit 'b2i')
   1.726 -        return x;
   1.727 -    }
   1.728 -    static long byteToLong(byte x) {  // bytecode: i2l (implicit 'b2i')
   1.729 -        return x;
   1.730 -    }
   1.731 -    static int byteToInt(byte x) {  // (implicit 'b2i')
   1.732 -        return x;
   1.733 -    }
   1.734 -    static short byteToShort(byte x) {  // bytecode: i2s (implicit 'b2i')
   1.735 -        return (short)x;
   1.736 -    }
   1.737 -    static char byteToChar(byte x) {  // bytecode: i2b (implicit 'b2i')
   1.738 -        return (char)x;
   1.739 -    }
   1.740 -    // narrow byte to boolean:
   1.741 -    static boolean byteToBoolean(byte x) {
   1.742 -        return toBoolean(x);
   1.743 -    }
   1.744 -
   1.745 -    // widen boolean to all types:
   1.746 -    static double booleanToDouble(boolean x) {
   1.747 -        return fromBoolean(x);
   1.748 -    }
   1.749 -    static float booleanToFloat(boolean x) {
   1.750 -        return fromBoolean(x);
   1.751 -    }
   1.752 -    static long booleanToLong(boolean x) {
   1.753 -        return fromBoolean(x);
   1.754 -    }
   1.755 -    static int booleanToInt(boolean x) {
   1.756 -        return fromBoolean(x);
   1.757 -    }
   1.758 -    static short booleanToShort(boolean x) {
   1.759 -        return fromBoolean(x);
   1.760 -    }
   1.761 -    static char booleanToChar(boolean x) {
   1.762 -        return (char)fromBoolean(x);
   1.763 -    }
   1.764 -    static byte booleanToByte(boolean x) {
   1.765 -        return fromBoolean(x);
   1.766 -    }
   1.767 -
   1.768 -    // helpers to force boolean into the conversion scheme:
   1.769 -    static boolean toBoolean(byte x) {
   1.770 -        // see javadoc for MethodHandles.explicitCastArguments
   1.771 -        return ((x & 1) != 0);
   1.772 -    }
   1.773 -    static byte fromBoolean(boolean x) {
   1.774 -        // see javadoc for MethodHandles.explicitCastArguments
   1.775 -        return (x ? (byte)1 : (byte)0);
   1.776 -    }
   1.777 -
   1.778 -    private static final EnumMap<Wrapper, MethodHandle>[]
   1.779 -            CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
   1.780 -
   1.781 -    public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
   1.782 -        EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
   1.783 -        MethodHandle mh = cache.get(wdst);
   1.784 -        if (mh != null) {
   1.785 -            return mh;
   1.786 -        }
   1.787 -        // slow path
   1.788 -        Class<?> src = wsrc.primitiveType();
   1.789 -        Class<?> dst = wdst.primitiveType();
   1.790 -        MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
   1.791 -        if (wsrc == wdst) {
   1.792 -            mh = identity(src);
   1.793 -        } else if (wsrc == Wrapper.VOID) {
   1.794 -            mh = zeroConstantFunction(wdst);
   1.795 -        } else if (wdst == Wrapper.VOID) {
   1.796 -            mh = MethodHandles.dropArguments(EMPTY, 0, src);  // Defer back to MethodHandles.
   1.797 -        } else if (wsrc == Wrapper.OBJECT) {
   1.798 -            mh = unboxCast(dst);
   1.799 -        } else if (wdst == Wrapper.OBJECT) {
   1.800 -            mh = box(src);
   1.801 -        } else {
   1.802 -            assert(src.isPrimitive() && dst.isPrimitive());
   1.803 -            try {
   1.804 -                mh = IMPL_LOOKUP.findStatic(THIS_CLASS, src.getSimpleName()+"To"+capitalize(dst.getSimpleName()), type);
   1.805 -            } catch (ReflectiveOperationException ex) {
   1.806 -                mh = null;
   1.807 -            }
   1.808 -        }
   1.809 -        if (mh != null) {
   1.810 -            assert(mh.type() == type) : mh;
   1.811 -            cache.put(wdst, mh);
   1.812 -            return mh;
   1.813 -        }
   1.814 -
   1.815 -        throw new IllegalArgumentException("cannot find primitive conversion function for " +
   1.816 -                                           src.getSimpleName()+" -> "+dst.getSimpleName());
   1.817 -    }
   1.818 -
   1.819 -    public static MethodHandle convertPrimitive(Class<?> src, Class<?> dst) {
   1.820 -        return convertPrimitive(Wrapper.forPrimitiveType(src), Wrapper.forPrimitiveType(dst));
   1.821 -    }
   1.822 -
   1.823 -    private static String capitalize(String x) {
   1.824 -        return Character.toUpperCase(x.charAt(0))+x.substring(1);
   1.825 -    }
   1.826 -
   1.827 -    /// Collection of multiple arguments.
   1.828 -
   1.829 -    public static Object convertArrayElements(Class<?> arrayType, Object array) {
   1.830 -        Class<?> src = array.getClass().getComponentType();
   1.831 -        Class<?> dst = arrayType.getComponentType();
   1.832 -        if (src == null || dst == null)  throw new IllegalArgumentException("not array type");
   1.833 -        Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
   1.834 -        Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
   1.835 -        int length;
   1.836 -        if (sw == null) {
   1.837 -            Object[] a = (Object[]) array;
   1.838 -            length = a.length;
   1.839 -            if (dw == null)
   1.840 -                return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
   1.841 -            Object res = dw.makeArray(length);
   1.842 -            dw.copyArrayUnboxing(a, 0, res, 0, length);
   1.843 -            return res;
   1.844 -        }
   1.845 -        length = java.lang.reflect.Array.getLength(array);
   1.846 -        Object[] res;
   1.847 -        if (dw == null) {
   1.848 -            res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
   1.849 -        } else {
   1.850 -            res = new Object[length];
   1.851 -        }
   1.852 -        sw.copyArrayBoxing(array, 0, res, 0, length);
   1.853 -        if (dw == null)  return res;
   1.854 -        Object a = dw.makeArray(length);
   1.855 -        dw.copyArrayUnboxing(res, 0, a, 0, length);
   1.856 -        return a;
   1.857 -    }
   1.858 -
   1.859 -    private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
   1.860 -        MethodType type = MethodType.genericMethodType(nargs)
   1.861 -                .changeReturnType(rtype)
   1.862 -                .insertParameterTypes(0, ptypes);
   1.863 -        try {
   1.864 -            return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
   1.865 -        } catch (ReflectiveOperationException ex) {
   1.866 -            return null;
   1.867 -        }
   1.868 -    }
   1.869 -
   1.870 -    private static final Object[] NO_ARGS_ARRAY = {};
   1.871 -    private static Object[] makeArray(Object... args) { return args; }
   1.872 -    private static Object[] array() { return NO_ARGS_ARRAY; }
   1.873 -    private static Object[] array(Object a0)
   1.874 -                { return makeArray(a0); }
   1.875 -    private static Object[] array(Object a0, Object a1)
   1.876 -                { return makeArray(a0, a1); }
   1.877 -    private static Object[] array(Object a0, Object a1, Object a2)
   1.878 -                { return makeArray(a0, a1, a2); }
   1.879 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
   1.880 -                { return makeArray(a0, a1, a2, a3); }
   1.881 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.882 -                                  Object a4)
   1.883 -                { return makeArray(a0, a1, a2, a3, a4); }
   1.884 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.885 -                                  Object a4, Object a5)
   1.886 -                { return makeArray(a0, a1, a2, a3, a4, a5); }
   1.887 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.888 -                                  Object a4, Object a5, Object a6)
   1.889 -                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
   1.890 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.891 -                                  Object a4, Object a5, Object a6, Object a7)
   1.892 -                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
   1.893 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.894 -                                  Object a4, Object a5, Object a6, Object a7,
   1.895 -                                  Object a8)
   1.896 -                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
   1.897 -    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
   1.898 -                                  Object a4, Object a5, Object a6, Object a7,
   1.899 -                                  Object a8, Object a9)
   1.900 -                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
   1.901 -    private static MethodHandle[] makeArrays() {
   1.902 -        ArrayList<MethodHandle> mhs = new ArrayList<>();
   1.903 -        for (;;) {
   1.904 -            MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
   1.905 -            if (mh == null)  break;
   1.906 -            mhs.add(mh);
   1.907 -        }
   1.908 -        assert(mhs.size() == 11);  // current number of methods
   1.909 -        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
   1.910 -    }
   1.911 -    private static final MethodHandle[] ARRAYS = makeArrays();
   1.912 -
   1.913 -    // filling versions of the above:
   1.914 -    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
   1.915 -    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
   1.916 -        Object[] a = new Object[len];
   1.917 -        fillWithArguments(a, 0, args);
   1.918 -        return a;
   1.919 -    }
   1.920 -    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
   1.921 -        Object[] a = Arrays.copyOf(example, len);
   1.922 -        fillWithArguments(a, 0, args);
   1.923 -        return a;
   1.924 -    }
   1.925 -    private static void fillWithArguments(Object[] a, int pos, Object... args) {
   1.926 -        System.arraycopy(args, 0, a, pos, args.length);
   1.927 -    }
   1.928 -    // using Integer pos instead of int pos to avoid bootstrapping problems
   1.929 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
   1.930 -                { fillWithArguments(a, pos, a0); return a; }
   1.931 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
   1.932 -                { fillWithArguments(a, pos, a0, a1); return a; }
   1.933 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
   1.934 -                { fillWithArguments(a, pos, a0, a1, a2); return a; }
   1.935 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
   1.936 -                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
   1.937 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.938 -                                  Object a4)
   1.939 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
   1.940 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.941 -                                  Object a4, Object a5)
   1.942 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
   1.943 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.944 -                                  Object a4, Object a5, Object a6)
   1.945 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
   1.946 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.947 -                                  Object a4, Object a5, Object a6, Object a7)
   1.948 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
   1.949 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.950 -                                  Object a4, Object a5, Object a6, Object a7,
   1.951 -                                  Object a8)
   1.952 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
   1.953 -    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   1.954 -                                  Object a4, Object a5, Object a6, Object a7,
   1.955 -                                  Object a8, Object a9)
   1.956 -                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
   1.957 -    private static MethodHandle[] makeFillArrays() {
   1.958 -        ArrayList<MethodHandle> mhs = new ArrayList<>();
   1.959 -        mhs.add(null);  // there is no empty fill; at least a0 is required
   1.960 -        for (;;) {
   1.961 -            MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
   1.962 -            if (mh == null)  break;
   1.963 -            mhs.add(mh);
   1.964 -        }
   1.965 -        assert(mhs.size() == 11);  // current number of methods
   1.966 -        return mhs.toArray(new MethodHandle[0]);
   1.967 -    }
   1.968 -    private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
   1.969 -
   1.970 -    private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
   1.971 -        return Arrays.copyOf(a, a.length, arrayType);
   1.972 -    }
   1.973 -    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
   1.974 -        Object a = w.makeArray(boxes.length);
   1.975 -        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
   1.976 -        return a;
   1.977 -    }
   1.978 -
   1.979 -    /** Return a method handle that takes the indicated number of Object
   1.980 -     *  arguments and returns an Object array of them, as if for varargs.
   1.981 -     */
   1.982 -    public static MethodHandle varargsArray(int nargs) {
   1.983 -        MethodHandle mh = ARRAYS[nargs];
   1.984 -        if (mh != null)  return mh;
   1.985 -        mh = findCollector("array", nargs, Object[].class);
   1.986 -        if (mh != null)  return ARRAYS[nargs] = mh;
   1.987 -        mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
   1.988 -        assert(assertCorrectArity(mh, nargs));
   1.989 -        return ARRAYS[nargs] = mh;
   1.990 -    }
   1.991 -
   1.992 -    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
   1.993 -        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
   1.994 -        return true;
   1.995 -    }
   1.996 -
   1.997 -    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
   1.998 -        // Build up the result mh as a sequence of fills like this:
   1.999 -        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
  1.1000 -        // The various fill(_,10*I,___*[J]) are reusable.
  1.1001 -        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
  1.1002 -        int rightLen = nargs - leftLen;
  1.1003 -        MethodHandle leftCollector = newArray.bindTo(nargs);
  1.1004 -        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
  1.1005 -        MethodHandle mh = finisher;
  1.1006 -        if (rightLen > 0) {
  1.1007 -            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
  1.1008 -            if (mh == ARRAY_IDENTITY)
  1.1009 -                mh = rightFiller;
  1.1010 -            else
  1.1011 -                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
  1.1012 -        }
  1.1013 -        if (mh == ARRAY_IDENTITY)
  1.1014 -            mh = leftCollector;
  1.1015 -        else
  1.1016 -            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
  1.1017 -        return mh;
  1.1018 -    }
  1.1019 -
  1.1020 -    private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
  1.1021 -    private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
  1.1022 -    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
  1.1023 -     *  fills a[L]..a[N-1] with corresponding arguments,
  1.1024 -     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
  1.1025 -     */
  1.1026 -    private static MethodHandle fillToRight(int nargs) {
  1.1027 -        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
  1.1028 -        if (filler != null)  return filler;
  1.1029 -        filler = buildFiller(nargs);
  1.1030 -        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
  1.1031 -        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
  1.1032 -    }
  1.1033 -    private static MethodHandle buildFiller(int nargs) {
  1.1034 -        if (nargs <= LEFT_ARGS)
  1.1035 -            return ARRAY_IDENTITY;  // no args to fill; return the array unchanged
  1.1036 -        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
  1.1037 -        final int CHUNK = LEFT_ARGS;
  1.1038 -        int rightLen = nargs % CHUNK;
  1.1039 -        int midLen = nargs - rightLen;
  1.1040 -        if (rightLen == 0) {
  1.1041 -            midLen = nargs - (rightLen = CHUNK);
  1.1042 -            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
  1.1043 -                // build some precursors from left to right
  1.1044 -                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
  1.1045 -                    if (j > LEFT_ARGS)  fillToRight(j);
  1.1046 -            }
  1.1047 -        }
  1.1048 -        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
  1.1049 -        assert(rightLen > 0);
  1.1050 -        MethodHandle midFill = fillToRight(midLen);  // recursive fill
  1.1051 -        MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
  1.1052 -        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
  1.1053 -        assert(rightFill.type().parameterCount() == 1 + rightLen);
  1.1054 -
  1.1055 -        // Combine the two fills:
  1.1056 -        //   right(mid(a, x10..x19), x20..x23)
  1.1057 -        // The final product will look like this:
  1.1058 -        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
  1.1059 -        if (midLen == LEFT_ARGS)
  1.1060 -            return rightFill;
  1.1061 -        else
  1.1062 -            return MethodHandles.collectArguments(rightFill, 0, midFill);
  1.1063 -    }
  1.1064 -
  1.1065 -    // Type-polymorphic version of varargs maker.
  1.1066 -    private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
  1.1067 -        = new ClassValue<MethodHandle[]>() {
  1.1068 -            @Override
  1.1069 -            protected MethodHandle[] computeValue(Class<?> type) {
  1.1070 -                return new MethodHandle[256];
  1.1071 -            }
  1.1072 -    };
  1.1073 -
  1.1074 -    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
  1.1075 -
  1.1076 -    /** Return a method handle that takes the indicated number of
  1.1077 -     *  typed arguments and returns an array of them.
  1.1078 -     *  The type argument is the array type.
  1.1079 -     */
  1.1080 -    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
  1.1081 -        Class<?> elemType = arrayType.getComponentType();
  1.1082 -        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
  1.1083 -        // FIXME: Need more special casing and caching here.
  1.1084 -        if (nargs >= MAX_JVM_ARITY/2 - 1) {
  1.1085 -            int slots = nargs;
  1.1086 -            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
  1.1087 -            if (arrayType == double[].class || arrayType == long[].class)
  1.1088 -                slots *= 2;
  1.1089 -            if (slots > MAX_ARRAY_SLOTS)
  1.1090 -                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
  1.1091 -        }
  1.1092 -        if (elemType == Object.class)
  1.1093 -            return varargsArray(nargs);
  1.1094 -        // other cases:  primitive arrays, subtypes of Object[]
  1.1095 -        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
  1.1096 -        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
  1.1097 -        if (mh != null)  return mh;
  1.1098 -        if (elemType.isPrimitive()) {
  1.1099 -            MethodHandle builder = FILL_NEW_ARRAY;
  1.1100 -            MethodHandle producer = buildArrayProducer(arrayType);
  1.1101 -            mh = buildVarargsArray(builder, producer, nargs);
  1.1102 -        } else {
  1.1103 -            @SuppressWarnings("unchecked")
  1.1104 -            Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
  1.1105 -            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
  1.1106 -            MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
  1.1107 -            MethodHandle producer = ARRAY_IDENTITY;
  1.1108 -            mh = buildVarargsArray(builder, producer, nargs);
  1.1109 -        }
  1.1110 -        mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
  1.1111 -        assert(assertCorrectArity(mh, nargs));
  1.1112 -        if (nargs < cache.length)
  1.1113 -            cache[nargs] = mh;
  1.1114 -        return mh;
  1.1115 -    }
  1.1116 -
  1.1117 -    private static MethodHandle buildArrayProducer(Class<?> arrayType) {
  1.1118 -        Class<?> elemType = arrayType.getComponentType();
  1.1119 -        if (elemType.isPrimitive())
  1.1120 -            return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
  1.1121 -        else
  1.1122 -            return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
  1.1123 -    }
  1.1124 -
  1.1125 -    // List version of varargs maker.
  1.1126 -
  1.1127 -    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
  1.1128 -    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
  1.1129 -    private static List<Object> list() { return NO_ARGS_LIST; }
  1.1130 -    private static List<Object> list(Object a0)
  1.1131 -                { return makeList(a0); }
  1.1132 -    private static List<Object> list(Object a0, Object a1)
  1.1133 -                { return makeList(a0, a1); }
  1.1134 -    private static List<Object> list(Object a0, Object a1, Object a2)
  1.1135 -                { return makeList(a0, a1, a2); }
  1.1136 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
  1.1137 -                { return makeList(a0, a1, a2, a3); }
  1.1138 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1139 -                                     Object a4)
  1.1140 -                { return makeList(a0, a1, a2, a3, a4); }
  1.1141 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1142 -                                     Object a4, Object a5)
  1.1143 -                { return makeList(a0, a1, a2, a3, a4, a5); }
  1.1144 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1145 -                                     Object a4, Object a5, Object a6)
  1.1146 -                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
  1.1147 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1148 -                                     Object a4, Object a5, Object a6, Object a7)
  1.1149 -                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
  1.1150 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1151 -                                     Object a4, Object a5, Object a6, Object a7,
  1.1152 -                                     Object a8)
  1.1153 -                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  1.1154 -    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
  1.1155 -                                     Object a4, Object a5, Object a6, Object a7,
  1.1156 -                                     Object a8, Object a9)
  1.1157 -                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  1.1158 -    private static MethodHandle[] makeLists() {
  1.1159 -        ArrayList<MethodHandle> mhs = new ArrayList<>();
  1.1160 -        for (;;) {
  1.1161 -            MethodHandle mh = findCollector("list", mhs.size(), List.class);
  1.1162 -            if (mh == null)  break;
  1.1163 -            mhs.add(mh);
  1.1164 -        }
  1.1165 -        assert(mhs.size() == 11);  // current number of methods
  1.1166 -        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
  1.1167 -    }
  1.1168 -    private static final MethodHandle[] LISTS = makeLists();
  1.1169 -
  1.1170 -    /** Return a method handle that takes the indicated number of Object
  1.1171 -     *  arguments and returns a List.
  1.1172 -     */
  1.1173 -    public static MethodHandle varargsList(int nargs) {
  1.1174 -        MethodHandle mh = LISTS[nargs];
  1.1175 -        if (mh != null)  return mh;
  1.1176 -        mh = findCollector("list", nargs, List.class);
  1.1177 -        if (mh != null)  return LISTS[nargs] = mh;
  1.1178 -        return LISTS[nargs] = buildVarargsList(nargs);
  1.1179 -    }
  1.1180 -    private static MethodHandle buildVarargsList(int nargs) {
  1.1181 -        return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
  1.1182 -    }
  1.1183 -
  1.1184 -    // handy shared exception makers (they simplify the common case code)
  1.1185 -    private static InternalError newInternalError(String message, Throwable cause) {
  1.1186 -        return new InternalError(message, cause);
  1.1187 -    }
  1.1188 -    private static InternalError newInternalError(Throwable cause) {
  1.1189 -        return new InternalError(cause);
  1.1190 -    }
  1.1191 -}