23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package sun.dyn.util; |
26 package sun.dyn.util; |
27 |
27 |
28 import java.dyn.*; |
28 import java.dyn.MethodHandle; |
|
29 import java.dyn.MethodHandles; |
29 import java.dyn.MethodHandles.Lookup; |
30 import java.dyn.MethodHandles.Lookup; |
|
31 import java.dyn.MethodType; |
30 import java.util.ArrayList; |
32 import java.util.ArrayList; |
31 import java.util.Arrays; |
33 import java.util.Arrays; |
32 import java.util.EnumMap; |
34 import java.util.EnumMap; |
33 import java.util.List; |
35 import java.util.List; |
34 import sun.dyn.Access; |
|
35 import sun.dyn.AdapterMethodHandle; |
|
36 import sun.dyn.MethodHandleImpl; |
|
37 import static sun.dyn.MemberName.uncaughtException; |
|
38 |
36 |
39 public class ValueConversions { |
37 public class ValueConversions { |
40 private static final Access IMPL_TOKEN = Access.getToken(); |
38 private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); |
41 private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN); |
|
42 |
39 |
43 private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) { |
40 private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) { |
44 @SuppressWarnings("unchecked") |
41 @SuppressWarnings("unchecked") |
45 EnumMap<Wrapper, MethodHandle>[] caches |
42 EnumMap<Wrapper, MethodHandle>[] caches |
46 = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here |
43 = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here |
155 mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase()); |
152 mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase()); |
156 } catch (ReflectiveOperationException ex) { |
153 } catch (ReflectiveOperationException ex) { |
157 mh = null; |
154 mh = null; |
158 } |
155 } |
159 } else { |
156 } else { |
160 mh = retype(type, unbox(wrap, !exact, raw)); |
157 mh = unbox(wrap, !exact, raw).asType(type); |
161 } |
158 } |
162 if (mh != null) { |
159 if (mh != null) { |
163 cache.put(wrap, mh); |
160 cache.put(wrap, mh); |
164 return mh; |
161 return mh; |
165 } |
162 } |
291 mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type); |
288 mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type); |
292 } catch (ReflectiveOperationException ex) { |
289 } catch (ReflectiveOperationException ex) { |
293 mh = null; |
290 mh = null; |
294 } |
291 } |
295 } else { |
292 } else { |
296 mh = retype(type.erase(), box(wrap, !exact, raw)); |
293 mh = box(wrap, !exact, raw).asType(type.erase()); |
297 } |
294 } |
298 if (mh != null) { |
295 if (mh != null) { |
299 cache.put(wrap, mh); |
296 cache.put(wrap, mh); |
300 return mh; |
297 return mh; |
301 } |
298 } |
550 */ |
547 */ |
551 static int identity(int x) { |
548 static int identity(int x) { |
552 return x; |
549 return x; |
553 } |
550 } |
554 |
551 |
|
552 static byte identity(byte x) { |
|
553 return x; |
|
554 } |
|
555 |
|
556 static short identity(short x) { |
|
557 return x; |
|
558 } |
|
559 |
|
560 static boolean identity(boolean x) { |
|
561 return x; |
|
562 } |
|
563 |
|
564 static char identity(char x) { |
|
565 return x; |
|
566 } |
|
567 |
555 /** |
568 /** |
556 * Identity function on longs. |
569 * Identity function on longs. |
557 * @param x an arbitrary long value |
570 * @param x an arbitrary long value |
558 * @return the same value x |
571 * @return the same value x |
559 */ |
572 */ |
560 static long identity(long x) { |
573 static long identity(long x) { |
|
574 return x; |
|
575 } |
|
576 |
|
577 static float identity(float x) { |
|
578 return x; |
|
579 } |
|
580 |
|
581 static double identity(double x) { |
561 return x; |
582 return x; |
562 } |
583 } |
563 |
584 |
564 /** |
585 /** |
565 * Identity function, with reference cast. |
586 * Identity function, with reference cast. |
588 ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType); |
609 ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType); |
589 ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType); |
610 ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType); |
590 IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType); |
611 IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType); |
591 EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1)); |
612 EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1)); |
592 } catch (Exception ex) { |
613 } catch (Exception ex) { |
593 throw uncaughtException(ex); |
614 Error err = new InternalError("uncaught exception"); |
|
615 err.initCause(ex); |
|
616 throw err; |
594 } |
617 } |
595 } |
618 } |
596 |
619 |
597 private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS |
620 private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS |
598 = new EnumMap<Wrapper, MethodHandle>(Wrapper.class); |
621 = new EnumMap<Wrapper, MethodHandle>(Wrapper.class); |
620 mh = ALWAYS_NULL; |
643 mh = ALWAYS_NULL; |
621 else |
644 else |
622 mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); |
645 mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); |
623 if (exact) { |
646 if (exact) { |
624 MethodType xmt = MethodType.methodType(type, Object.class); |
647 MethodType xmt = MethodType.methodType(type, Object.class); |
625 mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh); |
648 mh = MethodHandles.explicitCastArguments(mh, xmt); |
|
649 //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh); |
626 } |
650 } |
627 if (cache != null) |
651 if (cache != null) |
628 cache.put(wrap, mh); |
652 cache.put(wrap, mh); |
629 return mh; |
653 return mh; |
630 } |
654 } |
632 public static MethodHandle identity() { |
656 public static MethodHandle identity() { |
633 return IDENTITY; |
657 return IDENTITY; |
634 } |
658 } |
635 |
659 |
636 public static MethodHandle identity(Class<?> type) { |
660 public static MethodHandle identity(Class<?> type) { |
637 if (type == Object.class) |
661 // This stuff has been moved into MethodHandles: |
638 return IDENTITY; |
662 return MethodHandles.identity(type); |
639 else if (!type.isPrimitive()) |
663 } |
640 return retype(MethodType.methodType(type, type), IDENTITY); |
664 |
641 else |
665 public static MethodHandle identity(Wrapper wrap) { |
642 return identity(Wrapper.forPrimitiveType(type)); |
|
643 } |
|
644 |
|
645 static MethodHandle identity(Wrapper wrap) { |
|
646 EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1]; |
666 EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1]; |
647 MethodHandle mh = cache.get(wrap); |
667 MethodHandle mh = cache.get(wrap); |
648 if (mh != null) { |
668 if (mh != null) { |
649 return mh; |
669 return mh; |
650 } |
670 } |
663 if (mh != null) { |
683 if (mh != null) { |
664 cache.put(wrap, mh); |
684 cache.put(wrap, mh); |
665 return mh; |
685 return mh; |
666 } |
686 } |
667 |
687 |
668 // use a raw conversion |
|
669 if (wrap.isSingleWord() && wrap != Wrapper.INT) { |
|
670 mh = retype(type, identity(Wrapper.INT)); |
|
671 } else if (wrap.isDoubleWord() && wrap != Wrapper.LONG) { |
|
672 mh = retype(type, identity(Wrapper.LONG)); |
|
673 } |
|
674 if (mh != null) { |
688 if (mh != null) { |
675 cache.put(wrap, mh); |
689 cache.put(wrap, mh); |
676 return mh; |
690 return mh; |
677 } |
691 } |
678 throw new IllegalArgumentException("cannot find identity for " + wrap); |
692 throw new IllegalArgumentException("cannot find identity for " + wrap); |
679 } |
|
680 |
|
681 private static MethodHandle retype(MethodType type, MethodHandle mh) { |
|
682 return AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, type, mh); |
|
683 } |
693 } |
684 |
694 |
685 private static final Object[] NO_ARGS_ARRAY = {}; |
695 private static final Object[] NO_ARGS_ARRAY = {}; |
686 private static Object[] makeArray(Object... args) { return args; } |
696 private static Object[] makeArray(Object... args) { return args; } |
687 private static Object[] array() { return NO_ARGS_ARRAY; } |
697 private static Object[] array() { return NO_ARGS_ARRAY; } |