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