1.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/Wrapper.java Sun Aug 17 20:09:05 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,614 +0,0 @@
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 -}