426 return x;
427 }
428
429 /**
430 * Identity function on longs.
431 * @param x an arbitrary long value
432 * @return the same value x
433 */
434 static long identity(long x) {
435 return x;
436 }
437
438 static float identity(float x) {
439 return x;
440 }
441
442 static double identity(double x) {
443 return x;
444 }
445
446 /**
447 * Identity function, with reference cast.
448 * @param t an arbitrary reference type
449 * @param x an arbitrary reference value
450 * @return the same value x
451 */
452 @SuppressWarnings("unchecked")
453 static <T,U> T castReference(Class<? extends T> t, U x) {
454 // inlined Class.cast because we can't ForceInline it
455 if (x != null && !t.isInstance(x))
456 throw newClassCastException(t, x);
457 return (T) x;
458 }
459
460 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
461 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
462 }
463
464 private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
465 ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
466 static {
467 try {
468 MethodType idType = MethodType.genericMethodType(1);
469 MethodType castType = idType.insertParameterTypes(0, Class.class);
470 MethodType ignoreType = idType.changeReturnType(void.class);
471 MethodType zeroObjectType = MethodType.genericMethodType(0);
472 IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
473 //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
474 CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
475 ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
476 IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
477 EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
478 ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
479 FILL_NEW_ARRAY = IMPL_LOOKUP
480 .findStatic(THIS_CLASS, "fillNewArray",
481 MethodType.methodType(Object[].class, Integer.class, Object[].class));
482 FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
483 .findStatic(THIS_CLASS, "fillNewTypedArray",
484 MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
485 } catch (NoSuchMethodException | IllegalAccessException ex) {
486 throw newInternalError("uncaught exception", ex);
487 }
488 }
489
490 // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
491 static class LazyStatics {
492 private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
493 static {
494 try {
495 //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
496 COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
497 COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
498 MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
499 } catch (ReflectiveOperationException ex) {
500 throw newInternalError("uncaught exception", ex);
501 }
502 }
503 }
504
505 private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
506 = newWrapperCaches(1);
507
508 /** Return a method that casts its sole argument (an Object) to the given type
509 * and returns it as the given type.
510 */
511 public static MethodHandle cast(Class<?> type) {
512 if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
513 MethodHandle mh;
514 Wrapper wrap = null;
515 EnumMap<Wrapper, MethodHandle> cache = null;
516 if (Wrapper.isWrapperType(type)) {
517 wrap = Wrapper.forWrapperType(type);
518 cache = WRAPPER_CASTS[0];
519 mh = cache.get(wrap);
520 if (mh != null) return mh;
521 }
522 mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
523 if (cache != null)
524 cache.put(wrap, mh);
525 return mh;
526 }
527
528 public static MethodHandle identity() {
529 return IDENTITY;
530 }
531
532 public static MethodHandle identity(Class<?> type) {
533 if (!type.isPrimitive())
534 // Reference identity has been moved into MethodHandles:
535 return MethodHandles.identity(type);
536 return identity(Wrapper.findPrimitiveType(type));
537 }
538
539 public static MethodHandle identity(Wrapper wrap) {
540 EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
541 MethodHandle mh = cache.get(wrap);
542 if (mh != null) {
|
426 return x;
427 }
428
429 /**
430 * Identity function on longs.
431 * @param x an arbitrary long value
432 * @return the same value x
433 */
434 static long identity(long x) {
435 return x;
436 }
437
438 static float identity(float x) {
439 return x;
440 }
441
442 static double identity(double x) {
443 return x;
444 }
445
446 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
447 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
448 }
449
450 private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
451 ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
452 static {
453 try {
454 MethodType idType = MethodType.genericMethodType(1);
455 MethodType ignoreType = idType.changeReturnType(void.class);
456 MethodType zeroObjectType = MethodType.genericMethodType(0);
457 IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
458 CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
459 ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
460 IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
461 EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
462 ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
463 FILL_NEW_ARRAY = IMPL_LOOKUP
464 .findStatic(THIS_CLASS, "fillNewArray",
465 MethodType.methodType(Object[].class, Integer.class, Object[].class));
466 FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
467 .findStatic(THIS_CLASS, "fillNewTypedArray",
468 MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
469 } catch (NoSuchMethodException | IllegalAccessException ex) {
470 throw newInternalError("uncaught exception", ex);
471 }
472 }
473
474 // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
475 static class LazyStatics {
476 private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
477 static {
478 try {
479 //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
480 COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
481 COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
482 MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
483 } catch (ReflectiveOperationException ex) {
484 throw newInternalError("uncaught exception", ex);
485 }
486 }
487 }
488
489 private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
490 = newWrapperCaches(1);
491
492 /** Return a method that casts its sole argument (an Object) to the given type
493 * and returns it as the given type.
494 */
495 public static MethodHandle cast(Class<?> type) {
496 return cast(type, CAST_REFERENCE);
497 }
498 public static MethodHandle cast(Class<?> type, MethodHandle castReference) {
499 if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
500 MethodHandle mh;
501 Wrapper wrap = null;
502 EnumMap<Wrapper, MethodHandle> cache = null;
503 if (Wrapper.isWrapperType(type)) {
504 wrap = Wrapper.forWrapperType(type);
505 cache = WRAPPER_CASTS[0];
506 mh = cache.get(wrap);
507 if (mh != null) return mh;
508 }
509 mh = MethodHandles.insertArguments(castReference, 0, type);
510 if (cache != null)
511 cache.put(wrap, mh);
512 return mh;
513 }
514
515 public static MethodHandle identity() {
516 return IDENTITY;
517 }
518
519 public static MethodHandle identity(Class<?> type) {
520 if (!type.isPrimitive())
521 // Reference identity has been moved into MethodHandles:
522 return MethodHandles.identity(type);
523 return identity(Wrapper.findPrimitiveType(type));
524 }
525
526 public static MethodHandle identity(Wrapper wrap) {
527 EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
528 MethodHandle mh = cache.get(wrap);
529 if (mh != null) {
|