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 -}