1 /* 2 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.invoke.util; 27 28 public enum Wrapper { 29 // wrapperType primitiveType char emptyArray format 30 BOOLEAN( Boolean.class, boolean.class, 'Z', new boolean[0], Format.unsigned( 1)), 31 // These must be in the order defined for widening primitive conversions in JLS 5.1.2 32 // Avoid boxing integral types here to defer initialization of internal caches 33 BYTE ( Byte.class, byte.class, 'B', new byte[0], Format.signed( 8)), 34 SHORT ( Short.class, short.class, 'S', new short[0], Format.signed( 16)), 35 CHAR (Character.class, char.class, 'C', new char[0], Format.unsigned(16)), 36 INT ( Integer.class, int.class, 'I', new int[0], Format.signed( 32)), 37 LONG ( Long.class, long.class, 'J', new long[0], Format.signed( 64)), 38 FLOAT ( Float.class, float.class, 'F', new float[0], Format.floating(32)), 39 DOUBLE ( Double.class, double.class, 'D', new double[0], Format.floating(64)), 40 OBJECT ( Object.class, Object.class, 'L', new Object[0], Format.other( 1)), 41 // VOID must be the last type, since it is "assignable" from any other type: 42 VOID ( Void.class, void.class, 'V', null, Format.other( 0)), 43 ; 44 45 private final Class<?> wrapperType; 46 private final Class<?> primitiveType; 47 private final char basicTypeChar; 48 private final Object emptyArray; 49 private final int format; 50 private final String wrapperSimpleName; 51 private final String primitiveSimpleName; 52 53 private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object emptyArray, int format) { 54 this.wrapperType = wtype; 55 this.primitiveType = ptype; 56 this.basicTypeChar = tchar; 57 this.emptyArray = emptyArray; 58 this.format = format; 59 this.wrapperSimpleName = wtype.getSimpleName(); 60 this.primitiveSimpleName = ptype.getSimpleName(); 61 } 62 63 /** For debugging, give the details of this wrapper. */ 64 public String detailString() { 65 return wrapperSimpleName+ 66 java.util.Arrays.asList(wrapperType, primitiveType, 67 basicTypeChar, zero(), 68 "0x"+Integer.toHexString(format)); 69 } 70 71 private abstract static class Format { 72 static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12; 73 static final int 74 SIGNED = (-1) << KIND_SHIFT, 75 UNSIGNED = 0 << KIND_SHIFT, 76 FLOATING = 1 << KIND_SHIFT; 77 static final int 78 SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1), 79 SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1); 80 static int format(int kind, int size, int slots) { 81 assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind); 82 assert((size & (size-1)) == 0); // power of two 83 assert((kind == SIGNED) ? (size > 0) : 84 (kind == UNSIGNED) ? (size > 0) : 85 (kind == FLOATING) ? (size == 32 || size == 64) : 86 false); 87 assert((slots == 2) ? (size == 64) : 88 (slots == 1) ? (size <= 32) : 89 false); 90 return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT); 91 } 92 static final int 93 INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT), 94 SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT), 95 BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT), 96 CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT), 97 FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT), 98 VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT), 99 NUM_MASK = (-1) << SIZE_SHIFT; 100 static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); } 101 static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); } 102 static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); } 103 static int other(int slots) { return slots << SLOT_SHIFT; } 104 } 105 106 /// format queries: 107 108 /** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */ 109 public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; } 110 /** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */ 111 public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; } 112 /** Does the wrapped value occupy a single JVM stack slot? */ 113 public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; } 114 /** Does the wrapped value occupy two JVM stack slots? */ 115 public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; } 116 /** Is the wrapped type numeric (not void or object)? */ 117 public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; } 118 /** Is the wrapped type a primitive other than float, double, or void? */ 119 public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; } 120 /** Is the wrapped type one of int, boolean, byte, char, or short? */ 121 public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); } 122 /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */ 123 public boolean isSigned() { return format < Format.VOID; } 124 /* Is the wrapped value an unsigned integral type (one of boolean or char)? */ 125 public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; } 126 /** Is the wrapped type either float or double? */ 127 public boolean isFloating() { return format >= Format.FLOAT; } 128 /** Is the wrapped type either void or a reference? */ 129 public boolean isOther() { return (format & ~Format.SLOT_MASK) == 0; } 130 131 /** Does the JLS 5.1.2 allow a variable of this wrapper's 132 * primitive type to be assigned from a value of the given wrapper's primitive type? 133 * Cases: 134 * <ul> 135 * <li>unboxing followed by widening primitive conversion 136 * <li>any type converted to {@code void} (i.e., dropping a method call's value) 137 * <li>boxing conversion followed by widening reference conversion to {@code Object} 138 * </ul> 139 * These are the cases allowed by MethodHandle.asType. 140 */ 141 public boolean isConvertibleFrom(Wrapper source) { 142 if (this == source) return true; 143 if (this.compareTo(source) < 0) { 144 // At best, this is a narrowing conversion. 145 return false; 146 } 147 // All conversions are allowed in the enum order between floats and signed ints. 148 // First detect non-signed non-float types (boolean, char, Object, void). 149 boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0); 150 if (!floatOrSigned) { 151 if (this.isOther()) return true; 152 // can convert char to int or wider, but nothing else 153 if (source.format == Format.CHAR) return true; 154 // no other conversions are classified as widening 155 return false; 156 } 157 // All signed and float conversions in the enum order are widening. 158 assert(this.isFloating() || this.isSigned()); 159 assert(source.isFloating() || source.isSigned()); 160 return true; 161 } 162 163 static { assert(checkConvertibleFrom()); } 164 private static boolean checkConvertibleFrom() { 165 // Check the matrix for correct classification of widening conversions. 166 for (Wrapper w : values()) { 167 assert(w.isConvertibleFrom(w)); 168 assert(VOID.isConvertibleFrom(w)); 169 if (w != VOID) { 170 assert(OBJECT.isConvertibleFrom(w)); 171 assert(!w.isConvertibleFrom(VOID)); 172 } 173 // check relations with unsigned integral types: 174 if (w != CHAR) { 175 assert(!CHAR.isConvertibleFrom(w)); 176 if (!w.isConvertibleFrom(INT)) 177 assert(!w.isConvertibleFrom(CHAR)); 178 } 179 if (w != BOOLEAN) { 180 assert(!BOOLEAN.isConvertibleFrom(w)); 181 if (w != VOID && w != OBJECT) 182 assert(!w.isConvertibleFrom(BOOLEAN)); 183 } 184 // check relations with signed integral types: 185 if (w.isSigned()) { 186 for (Wrapper x : values()) { 187 if (w == x) continue; 188 if (x.isFloating()) 189 assert(!w.isConvertibleFrom(x)); 190 else if (x.isSigned()) { 191 if (w.compareTo(x) < 0) 192 assert(!w.isConvertibleFrom(x)); 193 else 194 assert(w.isConvertibleFrom(x)); 195 } 196 } 197 } 198 // check relations with floating types: 199 if (w.isFloating()) { 200 for (Wrapper x : values()) { 201 if (w == x) continue; 202 if (x.isSigned()) 203 assert(w.isConvertibleFrom(x)); 204 else if (x.isFloating()) { 205 if (w.compareTo(x) < 0) 206 assert(!w.isConvertibleFrom(x)); 207 else 208 assert(w.isConvertibleFrom(x)); 209 } 210 } 211 } 212 } 213 return true; // i.e., assert(true) 214 } 215 216 /** Produce a zero value for the given wrapper type. 217 * This will be a numeric zero for a number or character, 218 * false for a boolean, and null for a reference or void. 219 * The common thread is that this is what is contained 220 * in a default-initialized variable of the given primitive 221 * type. (For void, it is what a reflective method returns 222 * instead of no value at all.) 223 */ 224 public Object zero() { 225 switch (this) { 226 case BOOLEAN: 227 return Boolean.FALSE; 228 case INT: 229 return (Integer)0; 230 case BYTE: 231 return (Byte)(byte)0; 232 case CHAR: 233 return (Character)(char)0; 234 case SHORT: 235 return (Short)(short)0; 236 case LONG: 237 return (Long)(long)0; 238 case FLOAT: 239 return FLOAT_ZERO; 240 case DOUBLE: 241 return DOUBLE_ZERO; 242 case VOID: 243 case OBJECT: 244 default: 245 return null; 246 } 247 } 248 249 private static final Object DOUBLE_ZERO = (Double)(double)0; 250 private static final Object FLOAT_ZERO = (Float)(float)0; 251 252 /** Produce a zero value for the given wrapper type T. 253 * The optional argument must a type compatible with this wrapper. 254 * Equivalent to {@code this.cast(this.zero(), type)}. 255 */ 256 public <T> T zero(Class<T> type) { return convert(zero(), type); } 257 258 /** Return the wrapper that wraps values of the given type. 259 * The type may be {@code Object}, meaning the {@code OBJECT} wrapper. 260 * Otherwise, the type must be a primitive. 261 * @throws IllegalArgumentException for unexpected types 262 */ 263 public static Wrapper forPrimitiveType(Class<?> type) { 264 Wrapper w = findPrimitiveType(type); 265 if (w != null) return w; 266 if (type.isPrimitive()) 267 throw new InternalError(); // redo hash function 268 throw newIllegalArgumentException("not primitive: "+type); 269 } 270 271 static Wrapper findPrimitiveType(Class<?> type) { 272 Wrapper w = FROM_PRIM[hashPrim(type)]; 273 if (w != null && w.primitiveType == type) { 274 return w; 275 } 276 return null; 277 } 278 279 /** Return the wrapper that wraps values into the given wrapper type. 280 * If it is {@code Object}, return {@code OBJECT}. 281 * Otherwise, it must be a wrapper type. 282 * The type must not be a primitive type. 283 * @throws IllegalArgumentException for unexpected types 284 */ 285 public static Wrapper forWrapperType(Class<?> type) { 286 Wrapper w = findWrapperType(type); 287 if (w != null) return w; 288 for (Wrapper x : values()) 289 if (x.wrapperType == type) 290 throw new InternalError(); // redo hash function 291 throw newIllegalArgumentException("not wrapper: "+type); 292 } 293 294 static Wrapper findWrapperType(Class<?> type) { 295 Wrapper w = FROM_WRAP[hashWrap(type)]; 296 if (w != null && w.wrapperType == type) { 297 return w; 298 } 299 return null; 300 } 301 302 /** Return the wrapper that corresponds to the given bytecode 303 * signature character. Return {@code OBJECT} for the character 'L'. 304 * @throws IllegalArgumentException for any non-signature character or {@code '['}. 305 */ 306 public static Wrapper forBasicType(char type) { 307 Wrapper w = FROM_CHAR[hashChar(type)]; 308 if (w != null && w.basicTypeChar == type) { 309 return w; 310 } 311 for (Wrapper x : values()) 312 if (w.basicTypeChar == type) 313 throw new InternalError(); // redo hash function 314 throw newIllegalArgumentException("not basic type char: "+type); 315 } 316 317 /** Return the wrapper for the given type, if it is 318 * a primitive type, else return {@code OBJECT}. 319 */ 320 public static Wrapper forBasicType(Class<?> type) { 321 if (type.isPrimitive()) 322 return forPrimitiveType(type); 323 return OBJECT; // any reference, including wrappers or arrays 324 } 325 326 // Note on perfect hashes: 327 // for signature chars c, do (c + (c >> 1)) % 16 328 // for primitive type names n, do (n[0] + n[2]) % 16 329 // The type name hash works for both primitive and wrapper names. 330 // You can add "java/lang/Object" to the primitive names. 331 // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16. 332 private static final Wrapper[] FROM_PRIM = new Wrapper[16]; 333 private static final Wrapper[] FROM_WRAP = new Wrapper[16]; 334 private static final Wrapper[] FROM_CHAR = new Wrapper[16]; 335 private static int hashPrim(Class<?> x) { 336 String xn = x.getName(); 337 if (xn.length() < 3) return 0; 338 return (xn.charAt(0) + xn.charAt(2)) % 16; 339 } 340 private static int hashWrap(Class<?> x) { 341 String xn = x.getName(); 342 final int offset = 10; assert(offset == "java.lang.".length()); 343 if (xn.length() < offset+3) return 0; 344 return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16; 345 } 346 private static int hashChar(char x) { 347 return (x + (x >> 1)) % 16; 348 } 349 static { 350 for (Wrapper w : values()) { 351 int pi = hashPrim(w.primitiveType); 352 int wi = hashWrap(w.wrapperType); 353 int ci = hashChar(w.basicTypeChar); 354 assert(FROM_PRIM[pi] == null); 355 assert(FROM_WRAP[wi] == null); 356 assert(FROM_CHAR[ci] == null); 357 FROM_PRIM[pi] = w; 358 FROM_WRAP[wi] = w; 359 FROM_CHAR[ci] = w; 360 } 361 //assert(jdk.sun.invoke.util.WrapperTest.test(false)); 362 } 363 364 /** What is the primitive type wrapped by this wrapper? */ 365 public Class<?> primitiveType() { return primitiveType; } 366 367 /** What is the wrapper type for this wrapper? */ 368 public Class<?> wrapperType() { return wrapperType; } 369 370 /** What is the wrapper type for this wrapper? 371 * Otherwise, the example type must be the wrapper type, 372 * or the corresponding primitive type. 373 * (For {@code OBJECT}, the example type can be any non-primitive, 374 * and is normalized to {@code Object.class}.) 375 * The resulting class type has the same type parameter. 376 */ 377 public <T> Class<T> wrapperType(Class<T> exampleType) { 378 if (exampleType == wrapperType) { 379 return exampleType; 380 } else if (exampleType == primitiveType || 381 wrapperType == Object.class || 382 exampleType.isInterface()) { 383 return forceType(wrapperType, exampleType); 384 } 385 throw newClassCastException(exampleType, primitiveType); 386 } 387 388 private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) { 389 return new ClassCastException(actual + " is not compatible with " + expected); 390 } 391 392 /** If {@code type} is a primitive type, return the corresponding 393 * wrapper type, else return {@code type} unchanged. 394 */ 395 public static <T> Class<T> asWrapperType(Class<T> type) { 396 if (type.isPrimitive()) { 397 return forPrimitiveType(type).wrapperType(type); 398 } 399 return type; 400 } 401 402 /** If {@code type} is a wrapper type, return the corresponding 403 * primitive type, else return {@code type} unchanged. 404 */ 405 public static <T> Class<T> asPrimitiveType(Class<T> type) { 406 Wrapper w = findWrapperType(type); 407 if (w != null) { 408 return forceType(w.primitiveType(), type); 409 } 410 return type; 411 } 412 413 /** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */ 414 public static boolean isWrapperType(Class<?> type) { 415 return findWrapperType(type) != null; 416 } 417 418 /** Query: Is the given type a primitive, such as {@code int} or {@code void}? */ 419 public static boolean isPrimitiveType(Class<?> type) { 420 return type.isPrimitive(); 421 } 422 423 /** What is the bytecode signature character for this type? 424 * All non-primitives, including array types, report as 'L', the signature character for references. 425 */ 426 public static char basicTypeChar(Class<?> type) { 427 if (!type.isPrimitive()) 428 return 'L'; 429 else 430 return forPrimitiveType(type).basicTypeChar(); 431 } 432 433 /** What is the bytecode signature character for this wrapper's 434 * primitive type? 435 */ 436 public char basicTypeChar() { return basicTypeChar; } 437 438 /** What is the simple name of the wrapper type? 439 */ 440 public String wrapperSimpleName() { return wrapperSimpleName; } 441 442 /** What is the simple name of the primitive type? 443 */ 444 public String primitiveSimpleName() { return primitiveSimpleName; } 445 446 // /** Wrap a value in the given type, which may be either a primitive or wrapper type. 447 // * Performs standard primitive conversions, including truncation and float conversions. 448 // */ 449 // public static <T> T wrap(Object x, Class<T> type) { 450 // return Wrapper.valueOf(type).cast(x, type); 451 // } 452 453 /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type. 454 * The given target type must be this wrapper's primitive or wrapper type. 455 * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check. 456 * Performs standard primitive conversions, including truncation and float conversions. 457 * The given type must be compatible with this wrapper. That is, it must either 458 * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else 459 * it must be the wrapper's primitive type. 460 * Primitive conversions are only performed if the given type is itself a primitive. 461 * @throws ClassCastException if the given type is not compatible with this wrapper 462 */ 463 public <T> T cast(Object x, Class<T> type) { 464 return convert(x, type, true); 465 } 466 467 /** Convert a wrapped value to the given type. 468 * The given target type must be this wrapper's primitive or wrapper type. 469 * This is equivalent to {@link #cast}, except that it refuses to perform 470 * narrowing primitive conversions. 471 */ 472 public <T> T convert(Object x, Class<T> type) { 473 return convert(x, type, false); 474 } 475 476 private <T> T convert(Object x, Class<T> type, boolean isCast) { 477 if (this == OBJECT) { 478 // If the target wrapper is OBJECT, just do a reference cast. 479 // If the target type is an interface, perform no runtime check. 480 // (This loophole is safe, and is allowed by the JVM verifier.) 481 // If the target type is a primitive, change it to a wrapper. 482 assert(!type.isPrimitive()); 483 if (!type.isInterface()) 484 type.cast(x); 485 @SuppressWarnings("unchecked") 486 T result = (T) x; // unchecked warning is expected here 487 return result; 488 } 489 Class<T> wtype = wrapperType(type); 490 if (wtype.isInstance(x)) { 491 return wtype.cast(x); 492 } 493 if (!isCast) { 494 Class<?> sourceType = x.getClass(); // throw NPE if x is null 495 Wrapper source = findWrapperType(sourceType); 496 if (source == null || !this.isConvertibleFrom(source)) { 497 throw newClassCastException(wtype, sourceType); 498 } 499 } else if (x == null) { 500 @SuppressWarnings("unchecked") 501 T z = (T) zero(); 502 return z; 503 } 504 @SuppressWarnings("unchecked") 505 T result = (T) wrap(x); // unchecked warning is expected here 506 assert (result == null ? Void.class : result.getClass()) == wtype; 507 return result; 508 } 509 510 /** Cast a reference type to another reference type. 511 * If the target type is an interface, perform no runtime check. 512 * (This loophole is safe, and is allowed by the JVM verifier.) 513 * If the target type is a primitive, change it to a wrapper. 514 */ 515 static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) { 516 boolean z = (type == exampleType || 517 type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) || 518 exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) || 519 type == Object.class && !exampleType.isPrimitive()); 520 if (!z) 521 System.out.println(type+" <= "+exampleType); 522 assert(type == exampleType || 523 type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) || 524 exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) || 525 type == Object.class && !exampleType.isPrimitive()); 526 @SuppressWarnings("unchecked") 527 Class<T> result = (Class<T>) type; // unchecked warning is expected here 528 return result; 529 } 530 531 /** Wrap a value in this wrapper's type. 532 * Performs standard primitive conversions, including truncation and float conversions. 533 * Performs returns the unchanged reference for {@code OBJECT}. 534 * Returns null for {@code VOID}. 535 * Returns a zero value for a null input. 536 * @throws ClassCastException if this wrapper is numeric and the operand 537 * is not a number, character, boolean, or null 538 */ 539 public Object wrap(Object x) { 540 // do non-numeric wrappers first 541 switch (basicTypeChar) { 542 case 'L': return x; 543 case 'V': return null; 544 } 545 Number xn = numberValue(x); 546 switch (basicTypeChar) { 547 case 'I': return Integer.valueOf(xn.intValue()); 548 case 'J': return Long.valueOf(xn.longValue()); 549 case 'F': return Float.valueOf(xn.floatValue()); 550 case 'D': return Double.valueOf(xn.doubleValue()); 551 case 'S': return Short.valueOf((short) xn.intValue()); 552 case 'B': return Byte.valueOf((byte) xn.intValue()); 553 case 'C': return Character.valueOf((char) xn.intValue()); 554 case 'Z': return Boolean.valueOf(boolValue(xn.byteValue())); 555 } 556 throw new InternalError("bad wrapper"); 557 } 558 559 /** Wrap a value (an int or smaller value) in this wrapper's type. 560 * Performs standard primitive conversions, including truncation and float conversions. 561 * Produces an {@code Integer} for {@code OBJECT}, although the exact type 562 * of the operand is not known. 563 * Returns null for {@code VOID}. 564 */ 565 public Object wrap(int x) { 566 if (basicTypeChar == 'L') return (Integer)x; 567 switch (basicTypeChar) { 568 case 'L': throw newIllegalArgumentException("cannot wrap to object type"); 569 case 'V': return null; 570 case 'I': return Integer.valueOf(x); 571 case 'J': return Long.valueOf(x); 572 case 'F': return Float.valueOf(x); 573 case 'D': return Double.valueOf(x); 574 case 'S': return Short.valueOf((short) x); 575 case 'B': return Byte.valueOf((byte) x); 576 case 'C': return Character.valueOf((char) x); 577 case 'Z': return Boolean.valueOf(boolValue((byte) x)); 578 } 579 throw new InternalError("bad wrapper"); 580 } 581 582 private static Number numberValue(Object x) { 583 if (x instanceof Number) return (Number)x; 584 if (x instanceof Character) return (int)(Character)x; 585 if (x instanceof Boolean) return (Boolean)x ? 1 : 0; 586 // Remaining allowed case of void: Must be a null reference. 587 return (Number)x; 588 } 589 590 // Parameter type of boolValue must be byte, because 591 // MethodHandles.explicitCastArguments defines boolean 592 // conversion as first converting to byte. 593 private static boolean boolValue(byte bits) { 594 bits &= 1; // simple 31-bit zero extension 595 return (bits != 0); 596 } 597 598 private static RuntimeException newIllegalArgumentException(String message, Object x) { 599 return newIllegalArgumentException(message + x); 600 } 601 private static RuntimeException newIllegalArgumentException(String message) { 602 return new IllegalArgumentException(message); 603 } 604 605 // primitive array support 606 public Object makeArray(int len) { 607 return java.lang.reflect.Array.newInstance(primitiveType, len); 608 } 609 public Class<?> arrayType() { 610 return emptyArray.getClass(); 611 } 612 public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) { 613 if (a.getClass() != arrayType()) 614 arrayType().cast(a); // throw NPE or CCE if bad type 615 for (int i = 0; i < length; i++) { 616 Object value = values[i+vpos]; 617 value = convert(value, primitiveType); 618 java.lang.reflect.Array.set(a, i+apos, value); 619 } 620 } 621 public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) { 622 if (a.getClass() != arrayType()) 623 arrayType().cast(a); // throw NPE or CCE if bad type 624 for (int i = 0; i < length; i++) { 625 Object value = java.lang.reflect.Array.get(a, i+apos); 626 //Already done: value = convert(value, primitiveType); 627 assert(value.getClass() == wrapperType); 628 values[i+vpos] = value; 629 } 630 } 631 }