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