1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/Wrapper.java Sat Aug 09 11:11:13 2014 +0200
1.3 @@ -0,0 +1,614 @@
1.4 +/*
1.5 + * Copyright (c) 2008, 2012, 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 +public enum Wrapper {
1.32 + BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned(1)),
1.33 + // These must be in the order defined for widening primitive conversions in JLS 5.1.2
1.34 + BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)),
1.35 + SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)),
1.36 + CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)),
1.37 + INT(Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed(32)),
1.38 + LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)),
1.39 + FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
1.40 + DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
1.41 + //NULL(Null.class, null.class, 'N', null, null, Format.other(1)),
1.42 + OBJECT(Object.class, Object.class, 'L', null, new Object[0], Format.other(1)),
1.43 + // VOID must be the last type, since it is "assignable" from any other type:
1.44 + VOID(Void.class, void.class, 'V', null, null, Format.other(0)),
1.45 + ;
1.46 +
1.47 + private final Class<?> wrapperType;
1.48 + private final Class<?> primitiveType;
1.49 + private final char basicTypeChar;
1.50 + private final Object zero;
1.51 + private final Object emptyArray;
1.52 + private final int format;
1.53 + private final String wrapperSimpleName;
1.54 + private final String primitiveSimpleName;
1.55 +
1.56 + private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
1.57 + this.wrapperType = wtype;
1.58 + this.primitiveType = ptype;
1.59 + this.basicTypeChar = tchar;
1.60 + this.zero = zero;
1.61 + this.emptyArray = emptyArray;
1.62 + this.format = format;
1.63 + this.wrapperSimpleName = wtype.getSimpleName();
1.64 + this.primitiveSimpleName = ptype.getSimpleName();
1.65 + }
1.66 +
1.67 + /** For debugging, give the details of this wrapper. */
1.68 + public String detailString() {
1.69 + return wrapperSimpleName+
1.70 + java.util.Arrays.asList(wrapperType, primitiveType,
1.71 + basicTypeChar, zero,
1.72 + "0x"+Integer.toHexString(format));
1.73 + }
1.74 +
1.75 + private static abstract class Format {
1.76 + static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
1.77 + static final int
1.78 + SIGNED = (-1) << KIND_SHIFT,
1.79 + UNSIGNED = 0 << KIND_SHIFT,
1.80 + FLOATING = 1 << KIND_SHIFT;
1.81 + static final int
1.82 + SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
1.83 + SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
1.84 + static int format(int kind, int size, int slots) {
1.85 + assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
1.86 + assert((size & (size-1)) == 0); // power of two
1.87 + assert((kind == SIGNED) ? (size > 0) :
1.88 + (kind == UNSIGNED) ? (size > 0) :
1.89 + (kind == FLOATING) ? (size == 32 || size == 64) :
1.90 + false);
1.91 + assert((slots == 2) ? (size == 64) :
1.92 + (slots == 1) ? (size <= 32) :
1.93 + false);
1.94 + return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
1.95 + }
1.96 + static final int
1.97 + INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
1.98 + SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
1.99 + BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
1.100 + CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
1.101 + FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
1.102 + VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT),
1.103 + NUM_MASK = (-1) << SIZE_SHIFT;
1.104 + static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); }
1.105 + static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
1.106 + static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
1.107 + static int other(int slots) { return slots << SLOT_SHIFT; }
1.108 + }
1.109 +
1.110 + /// format queries:
1.111 +
1.112 + /** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */
1.113 + public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
1.114 + /** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */
1.115 + public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
1.116 + /** Does the wrapped value occupy a single JVM stack slot? */
1.117 + public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
1.118 + /** Does the wrapped value occupy two JVM stack slots? */
1.119 + public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
1.120 + /** Is the wrapped type numeric (not void or object)? */
1.121 + public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; }
1.122 + /** Is the wrapped type a primitive other than float, double, or void? */
1.123 + public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; }
1.124 + /** Is the wrapped type one of int, boolean, byte, char, or short? */
1.125 + public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
1.126 + /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
1.127 + public boolean isSigned() { return format < Format.VOID; }
1.128 + /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
1.129 + public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
1.130 + /** Is the wrapped type either float or double? */
1.131 + public boolean isFloating() { return format >= Format.FLOAT; }
1.132 + /** Is the wrapped type either void or a reference? */
1.133 + public boolean isOther() { return (format & ~Format.SLOT_MASK) == 0; }
1.134 +
1.135 + /** Does the JLS 5.1.2 allow a variable of this wrapper's
1.136 + * primitive type to be assigned from a value of the given wrapper's primitive type?
1.137 + * Cases:
1.138 + * <ul>
1.139 + * <li>unboxing followed by widening primitive conversion
1.140 + * <li>any type converted to {@code void} (i.e., dropping a method call's value)
1.141 + * <li>boxing conversion followed by widening reference conversion to {@code Object}
1.142 + * </ul>
1.143 + * These are the cases allowed by MethodHandle.asType.
1.144 + */
1.145 + public boolean isConvertibleFrom(Wrapper source) {
1.146 + if (this == source) return true;
1.147 + if (this.compareTo(source) < 0) {
1.148 + // At best, this is a narrowing conversion.
1.149 + return false;
1.150 + }
1.151 + // All conversions are allowed in the enum order between floats and signed ints.
1.152 + // First detect non-signed non-float types (boolean, char, Object, void).
1.153 + boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0);
1.154 + if (!floatOrSigned) {
1.155 + if (this.isOther()) return true;
1.156 + // can convert char to int or wider, but nothing else
1.157 + if (source.format == Format.CHAR) return true;
1.158 + // no other conversions are classified as widening
1.159 + return false;
1.160 + }
1.161 + // All signed and float conversions in the enum order are widening.
1.162 + assert(this.isFloating() || this.isSigned());
1.163 + assert(source.isFloating() || source.isSigned());
1.164 + return true;
1.165 + }
1.166 +
1.167 + static { assert(checkConvertibleFrom()); }
1.168 + private static boolean checkConvertibleFrom() {
1.169 + // Check the matrix for correct classification of widening conversions.
1.170 + for (Wrapper w : values()) {
1.171 + assert(w.isConvertibleFrom(w));
1.172 + assert(VOID.isConvertibleFrom(w));
1.173 + if (w != VOID) {
1.174 + assert(OBJECT.isConvertibleFrom(w));
1.175 + assert(!w.isConvertibleFrom(VOID));
1.176 + }
1.177 + // check relations with unsigned integral types:
1.178 + if (w != CHAR) {
1.179 + assert(!CHAR.isConvertibleFrom(w));
1.180 + if (!w.isConvertibleFrom(INT))
1.181 + assert(!w.isConvertibleFrom(CHAR));
1.182 + }
1.183 + if (w != BOOLEAN) {
1.184 + assert(!BOOLEAN.isConvertibleFrom(w));
1.185 + if (w != VOID && w != OBJECT)
1.186 + assert(!w.isConvertibleFrom(BOOLEAN));
1.187 + }
1.188 + // check relations with signed integral types:
1.189 + if (w.isSigned()) {
1.190 + for (Wrapper x : values()) {
1.191 + if (w == x) continue;
1.192 + if (x.isFloating())
1.193 + assert(!w.isConvertibleFrom(x));
1.194 + else if (x.isSigned()) {
1.195 + if (w.compareTo(x) < 0)
1.196 + assert(!w.isConvertibleFrom(x));
1.197 + else
1.198 + assert(w.isConvertibleFrom(x));
1.199 + }
1.200 + }
1.201 + }
1.202 + // check relations with floating types:
1.203 + if (w.isFloating()) {
1.204 + for (Wrapper x : values()) {
1.205 + if (w == x) continue;
1.206 + if (x.isSigned())
1.207 + assert(w.isConvertibleFrom(x));
1.208 + else if (x.isFloating()) {
1.209 + if (w.compareTo(x) < 0)
1.210 + assert(!w.isConvertibleFrom(x));
1.211 + else
1.212 + assert(w.isConvertibleFrom(x));
1.213 + }
1.214 + }
1.215 + }
1.216 + }
1.217 + return true; // i.e., assert(true)
1.218 + }
1.219 +
1.220 + /** Produce a zero value for the given wrapper type.
1.221 + * This will be a numeric zero for a number or character,
1.222 + * false for a boolean, and null for a reference or void.
1.223 + * The common thread is that this is what is contained
1.224 + * in a default-initialized variable of the given primitive
1.225 + * type. (For void, it is what a reflective method returns
1.226 + * instead of no value at all.)
1.227 + */
1.228 + public Object zero() { return zero; }
1.229 +
1.230 + /** Produce a zero value for the given wrapper type T.
1.231 + * The optional argument must a type compatible with this wrapper.
1.232 + * Equivalent to {@code this.cast(this.zero(), type)}.
1.233 + */
1.234 + public <T> T zero(Class<T> type) { return convert(zero, type); }
1.235 +
1.236 +// /** Produce a wrapper for the given wrapper or primitive type. */
1.237 +// public static Wrapper valueOf(Class<?> type) {
1.238 +// if (isPrimitiveType(type))
1.239 +// return forPrimitiveType(type);
1.240 +// else
1.241 +// return forWrapperType(type);
1.242 +// }
1.243 +
1.244 + /** Return the wrapper that wraps values of the given type.
1.245 + * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
1.246 + * Otherwise, the type must be a primitive.
1.247 + * @throws IllegalArgumentException for unexpected types
1.248 + */
1.249 + public static Wrapper forPrimitiveType(Class<?> type) {
1.250 + Wrapper w = findPrimitiveType(type);
1.251 + if (w != null) return w;
1.252 + if (type.isPrimitive())
1.253 + throw new InternalError(); // redo hash function
1.254 + throw newIllegalArgumentException("not primitive: "+type);
1.255 + }
1.256 +
1.257 + static Wrapper findPrimitiveType(Class<?> type) {
1.258 + Wrapper w = FROM_PRIM[hashPrim(type)];
1.259 + if (w != null && w.primitiveType == type) {
1.260 + return w;
1.261 + }
1.262 + return null;
1.263 + }
1.264 +
1.265 + /** Return the wrapper that wraps values into the given wrapper type.
1.266 + * If it is {@code Object}, return {@code OBJECT}.
1.267 + * Otherwise, it must be a wrapper type.
1.268 + * The type must not be a primitive type.
1.269 + * @throws IllegalArgumentException for unexpected types
1.270 + */
1.271 + public static Wrapper forWrapperType(Class<?> type) {
1.272 + Wrapper w = findWrapperType(type);
1.273 + if (w != null) return w;
1.274 + for (Wrapper x : values())
1.275 + if (x.wrapperType == type)
1.276 + throw new InternalError(); // redo hash function
1.277 + throw newIllegalArgumentException("not wrapper: "+type);
1.278 + }
1.279 +
1.280 + static Wrapper findWrapperType(Class<?> type) {
1.281 + Wrapper w = FROM_WRAP[hashWrap(type)];
1.282 + if (w != null && w.wrapperType == type) {
1.283 + return w;
1.284 + }
1.285 + return null;
1.286 + }
1.287 +
1.288 + /** Return the wrapper that corresponds to the given bytecode
1.289 + * signature character. Return {@code OBJECT} for the character 'L'.
1.290 + * @throws IllegalArgumentException for any non-signature character or {@code '['}.
1.291 + */
1.292 + public static Wrapper forBasicType(char type) {
1.293 + Wrapper w = FROM_CHAR[hashChar(type)];
1.294 + if (w != null && w.basicTypeChar == type) {
1.295 + return w;
1.296 + }
1.297 + for (Wrapper x : values())
1.298 + if (w.basicTypeChar == type)
1.299 + throw new InternalError(); // redo hash function
1.300 + throw newIllegalArgumentException("not basic type char: "+type);
1.301 + }
1.302 +
1.303 + /** Return the wrapper for the given type, if it is
1.304 + * a primitive type, else return {@code OBJECT}.
1.305 + */
1.306 + public static Wrapper forBasicType(Class<?> type) {
1.307 + if (type.isPrimitive())
1.308 + return forPrimitiveType(type);
1.309 + return OBJECT; // any reference, including wrappers or arrays
1.310 + }
1.311 +
1.312 + // Note on perfect hashes:
1.313 + // for signature chars c, do (c + (c >> 1)) % 16
1.314 + // for primitive type names n, do (n[0] + n[2]) % 16
1.315 + // The type name hash works for both primitive and wrapper names.
1.316 + // You can add "java/lang/Object" to the primitive names.
1.317 + // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
1.318 + private static final Wrapper[] FROM_PRIM = new Wrapper[16];
1.319 + private static final Wrapper[] FROM_WRAP = new Wrapper[16];
1.320 + private static final Wrapper[] FROM_CHAR = new Wrapper[16];
1.321 + private static int hashPrim(Class<?> x) {
1.322 + String xn = x.getName();
1.323 + if (xn.length() < 3) return 0;
1.324 + return (xn.charAt(0) + xn.charAt(2)) % 16;
1.325 + }
1.326 + private static int hashWrap(Class<?> x) {
1.327 + String xn = x.getName();
1.328 + final int offset = 10; assert(offset == "java.lang.".length());
1.329 + if (xn.length() < offset+3) return 0;
1.330 + return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
1.331 + }
1.332 + private static int hashChar(char x) {
1.333 + return (x + (x >> 1)) % 16;
1.334 + }
1.335 + static {
1.336 + for (Wrapper w : values()) {
1.337 + int pi = hashPrim(w.primitiveType);
1.338 + int wi = hashWrap(w.wrapperType);
1.339 + int ci = hashChar(w.basicTypeChar);
1.340 + assert(FROM_PRIM[pi] == null);
1.341 + assert(FROM_WRAP[wi] == null);
1.342 + assert(FROM_CHAR[ci] == null);
1.343 + FROM_PRIM[pi] = w;
1.344 + FROM_WRAP[wi] = w;
1.345 + FROM_CHAR[ci] = w;
1.346 + }
1.347 + //assert(jdk.sun.invoke.util.WrapperTest.test(false));
1.348 + }
1.349 +
1.350 + /** What is the primitive type wrapped by this wrapper? */
1.351 + public Class<?> primitiveType() { return primitiveType; }
1.352 +
1.353 + /** What is the wrapper type for this wrapper? */
1.354 + public Class<?> wrapperType() { return wrapperType; }
1.355 +
1.356 + /** What is the wrapper type for this wrapper?
1.357 + * Otherwise, the example type must be the wrapper type,
1.358 + * or the corresponding primitive type.
1.359 + * (For {@code OBJECT}, the example type can be any non-primitive,
1.360 + * and is normalized to {@code Object.class}.)
1.361 + * The resulting class type has the same type parameter.
1.362 + */
1.363 + public <T> Class<T> wrapperType(Class<T> exampleType) {
1.364 + if (exampleType == wrapperType) {
1.365 + return exampleType;
1.366 + } else if (exampleType == primitiveType ||
1.367 + wrapperType == Object.class ||
1.368 + exampleType.isInterface()) {
1.369 + return forceType(wrapperType, exampleType);
1.370 + }
1.371 + throw newClassCastException(exampleType, primitiveType);
1.372 + }
1.373 +
1.374 + private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
1.375 + return new ClassCastException(actual + " is not compatible with " + expected);
1.376 + }
1.377 +
1.378 + /** If {@code type} is a primitive type, return the corresponding
1.379 + * wrapper type, else return {@code type} unchanged.
1.380 + */
1.381 + public static <T> Class<T> asWrapperType(Class<T> type) {
1.382 + if (type.isPrimitive()) {
1.383 + return forPrimitiveType(type).wrapperType(type);
1.384 + }
1.385 + return type;
1.386 + }
1.387 +
1.388 + /** If {@code type} is a wrapper type, return the corresponding
1.389 + * primitive type, else return {@code type} unchanged.
1.390 + */
1.391 + public static <T> Class<T> asPrimitiveType(Class<T> type) {
1.392 + Wrapper w = findWrapperType(type);
1.393 + if (w != null) {
1.394 + return forceType(w.primitiveType(), type);
1.395 + }
1.396 + return type;
1.397 + }
1.398 +
1.399 + /** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
1.400 + public static boolean isWrapperType(Class<?> type) {
1.401 + return findWrapperType(type) != null;
1.402 + }
1.403 +
1.404 + /** Query: Is the given type a primitive, such as {@code int} or {@code void}? */
1.405 + public static boolean isPrimitiveType(Class<?> type) {
1.406 + return type.isPrimitive();
1.407 + }
1.408 +
1.409 + /** What is the bytecode signature character for this type?
1.410 + * All non-primitives, including array types, report as 'L', the signature character for references.
1.411 + */
1.412 + public static char basicTypeChar(Class<?> type) {
1.413 + if (!type.isPrimitive())
1.414 + return 'L';
1.415 + else
1.416 + return forPrimitiveType(type).basicTypeChar();
1.417 + }
1.418 +
1.419 + /** What is the bytecode signature character for this wrapper's
1.420 + * primitive type?
1.421 + */
1.422 + public char basicTypeChar() { return basicTypeChar; }
1.423 +
1.424 + /** What is the simple name of the wrapper type?
1.425 + */
1.426 + public String wrapperSimpleName() { return wrapperSimpleName; }
1.427 +
1.428 + /** What is the simple name of the primitive type?
1.429 + */
1.430 + public String primitiveSimpleName() { return primitiveSimpleName; }
1.431 +
1.432 +// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
1.433 +// * Performs standard primitive conversions, including truncation and float conversions.
1.434 +// */
1.435 +// public static <T> T wrap(Object x, Class<T> type) {
1.436 +// return Wrapper.valueOf(type).cast(x, type);
1.437 +// }
1.438 +
1.439 + /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
1.440 + * The given target type must be this wrapper's primitive or wrapper type.
1.441 + * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
1.442 + * Performs standard primitive conversions, including truncation and float conversions.
1.443 + * The given type must be compatible with this wrapper. That is, it must either
1.444 + * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
1.445 + * it must be the wrapper's primitive type.
1.446 + * Primitive conversions are only performed if the given type is itself a primitive.
1.447 + * @throws ClassCastException if the given type is not compatible with this wrapper
1.448 + */
1.449 + public <T> T cast(Object x, Class<T> type) {
1.450 + return convert(x, type, true);
1.451 + }
1.452 +
1.453 + /** Convert a wrapped value to the given type.
1.454 + * The given target type must be this wrapper's primitive or wrapper type.
1.455 + * This is equivalent to {@link #cast}, except that it refuses to perform
1.456 + * narrowing primitive conversions.
1.457 + */
1.458 + public <T> T convert(Object x, Class<T> type) {
1.459 + return convert(x, type, false);
1.460 + }
1.461 +
1.462 + private <T> T convert(Object x, Class<T> type, boolean isCast) {
1.463 + if (this == OBJECT) {
1.464 + // If the target wrapper is OBJECT, just do a reference cast.
1.465 + // If the target type is an interface, perform no runtime check.
1.466 + // (This loophole is safe, and is allowed by the JVM verifier.)
1.467 + // If the target type is a primitive, change it to a wrapper.
1.468 + assert(!type.isPrimitive());
1.469 + if (!type.isInterface())
1.470 + type.cast(x);
1.471 + @SuppressWarnings("unchecked")
1.472 + T result = (T) x; // unchecked warning is expected here
1.473 + return result;
1.474 + }
1.475 + Class<T> wtype = wrapperType(type);
1.476 + if (wtype.isInstance(x)) {
1.477 + return wtype.cast(x);
1.478 + }
1.479 + if (!isCast) {
1.480 + Class<?> sourceType = x.getClass(); // throw NPE if x is null
1.481 + Wrapper source = findWrapperType(sourceType);
1.482 + if (source == null || !this.isConvertibleFrom(source)) {
1.483 + throw newClassCastException(wtype, sourceType);
1.484 + }
1.485 + } else if (x == null) {
1.486 + @SuppressWarnings("unchecked")
1.487 + T z = (T) zero;
1.488 + return z;
1.489 + }
1.490 + @SuppressWarnings("unchecked")
1.491 + T result = (T) wrap(x); // unchecked warning is expected here
1.492 + assert (result == null ? Void.class : result.getClass()) == wtype;
1.493 + return result;
1.494 + }
1.495 +
1.496 + /** Cast a reference type to another reference type.
1.497 + * If the target type is an interface, perform no runtime check.
1.498 + * (This loophole is safe, and is allowed by the JVM verifier.)
1.499 + * If the target type is a primitive, change it to a wrapper.
1.500 + */
1.501 + static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
1.502 + boolean z = (type == exampleType ||
1.503 + type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
1.504 + exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
1.505 + type == Object.class && !exampleType.isPrimitive());
1.506 + if (!z)
1.507 + System.out.println(type+" <= "+exampleType);
1.508 + assert(type == exampleType ||
1.509 + type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
1.510 + exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
1.511 + type == Object.class && !exampleType.isPrimitive());
1.512 + @SuppressWarnings("unchecked")
1.513 + Class<T> result = (Class<T>) type; // unchecked warning is expected here
1.514 + return result;
1.515 + }
1.516 +
1.517 + /** Wrap a value in this wrapper's type.
1.518 + * Performs standard primitive conversions, including truncation and float conversions.
1.519 + * Performs returns the unchanged reference for {@code OBJECT}.
1.520 + * Returns null for {@code VOID}.
1.521 + * Returns a zero value for a null input.
1.522 + * @throws ClassCastException if this wrapper is numeric and the operand
1.523 + * is not a number, character, boolean, or null
1.524 + */
1.525 + public Object wrap(Object x) {
1.526 + // do non-numeric wrappers first
1.527 + switch (basicTypeChar) {
1.528 + case 'L': return x;
1.529 + case 'V': return null;
1.530 + }
1.531 + Number xn = numberValue(x);
1.532 + switch (basicTypeChar) {
1.533 + case 'I': return Integer.valueOf(xn.intValue());
1.534 + case 'J': return Long.valueOf(xn.longValue());
1.535 + case 'F': return Float.valueOf(xn.floatValue());
1.536 + case 'D': return Double.valueOf(xn.doubleValue());
1.537 + case 'S': return Short.valueOf((short) xn.intValue());
1.538 + case 'B': return Byte.valueOf((byte) xn.intValue());
1.539 + case 'C': return Character.valueOf((char) xn.intValue());
1.540 + case 'Z': return Boolean.valueOf(boolValue(xn.byteValue()));
1.541 + }
1.542 + throw new InternalError("bad wrapper");
1.543 + }
1.544 +
1.545 + /** Wrap a value (an int or smaller value) in this wrapper's type.
1.546 + * Performs standard primitive conversions, including truncation and float conversions.
1.547 + * Produces an {@code Integer} for {@code OBJECT}, although the exact type
1.548 + * of the operand is not known.
1.549 + * Returns null for {@code VOID}.
1.550 + */
1.551 + public Object wrap(int x) {
1.552 + if (basicTypeChar == 'L') return (Integer)x;
1.553 + switch (basicTypeChar) {
1.554 + case 'L': throw newIllegalArgumentException("cannot wrap to object type");
1.555 + case 'V': return null;
1.556 + case 'I': return Integer.valueOf(x);
1.557 + case 'J': return Long.valueOf(x);
1.558 + case 'F': return Float.valueOf(x);
1.559 + case 'D': return Double.valueOf(x);
1.560 + case 'S': return Short.valueOf((short) x);
1.561 + case 'B': return Byte.valueOf((byte) x);
1.562 + case 'C': return Character.valueOf((char) x);
1.563 + case 'Z': return Boolean.valueOf(boolValue((byte) x));
1.564 + }
1.565 + throw new InternalError("bad wrapper");
1.566 + }
1.567 +
1.568 + private static Number numberValue(Object x) {
1.569 + if (x instanceof Number) return (Number)x;
1.570 + if (x instanceof Character) return (int)(Character)x;
1.571 + if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
1.572 + // Remaining allowed case of void: Must be a null reference.
1.573 + return (Number)x;
1.574 + }
1.575 +
1.576 + // Parameter type of boolValue must be byte, because
1.577 + // MethodHandles.explicitCastArguments defines boolean
1.578 + // conversion as first converting to byte.
1.579 + private static boolean boolValue(byte bits) {
1.580 + bits &= 1; // simple 31-bit zero extension
1.581 + return (bits != 0);
1.582 + }
1.583 +
1.584 + private static RuntimeException newIllegalArgumentException(String message, Object x) {
1.585 + return newIllegalArgumentException(message + x);
1.586 + }
1.587 + private static RuntimeException newIllegalArgumentException(String message) {
1.588 + return new IllegalArgumentException(message);
1.589 + }
1.590 +
1.591 + // primitive array support
1.592 + public Object makeArray(int len) {
1.593 + return java.lang.reflect.Array.newInstance(primitiveType, len);
1.594 + }
1.595 + public Class<?> arrayType() {
1.596 + return emptyArray.getClass();
1.597 + }
1.598 + public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) {
1.599 + if (a.getClass() != arrayType())
1.600 + arrayType().cast(a); // throw NPE or CCE if bad type
1.601 + for (int i = 0; i < length; i++) {
1.602 + Object value = values[i+vpos];
1.603 + value = convert(value, primitiveType);
1.604 + java.lang.reflect.Array.set(a, i+apos, value);
1.605 + }
1.606 + }
1.607 + public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) {
1.608 + if (a.getClass() != arrayType())
1.609 + arrayType().cast(a); // throw NPE or CCE if bad type
1.610 + for (int i = 0; i < length; i++) {
1.611 + Object value = java.lang.reflect.Array.get(a, i+apos);
1.612 + //Already done: value = convert(value, primitiveType);
1.613 + assert(value.getClass() == wrapperType);
1.614 + values[i+vpos] = value;
1.615 + }
1.616 + }
1.617 +}