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.invoke.MethodHandle;
29 import java.lang.invoke.MethodHandles;
30 import java.lang.invoke.MethodHandles.Lookup;
31 import java.lang.invoke.MethodType;
32 import java.util.EnumMap;
33
34 public class ValueConversions {
35 private static final Class<?> THIS_CLASS = ValueConversions.class;
36 private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
37
38 /** Thread-safe canonicalized mapping from Wrapper to MethodHandle
39 * with unsynchronized reads and synchronized writes.
40 * It's safe to publish MethodHandles by data race because they are immutable. */
41 private static class WrapperCache {
42 /** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */
43 private final EnumMap<Wrapper, MethodHandle> map = new EnumMap<>(Wrapper.class);
44
45 public MethodHandle get(Wrapper w) {
46 return map.get(w);
47 }
48 public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
49 // Simulate CAS to avoid racy duplication
50 MethodHandle prev = map.putIfAbsent(w, mh);
51 if (prev != null) return prev;
52 return mh;
53 }
54 }
55
56 private static WrapperCache[] newWrapperCaches(int n) {
57 WrapperCache[] caches = new WrapperCache[n];
58 for (int i = 0; i < n; i++)
59 caches[i] = new WrapperCache();
60 return caches;
61 }
62
63 /// Converting references to values.
64
65 // There are several levels of this unboxing conversions:
66 // no conversions: exactly Integer.valueOf, etc.
67 // implicit conversions sanctioned by JLS 5.1.2, etc.
68 // explicit conversions as allowed by explicitCastArguments
69
70 static int unboxInteger(Integer x) {
71 return x;
72 }
73 static int unboxInteger(Object x, boolean cast) {
74 if (x instanceof Integer)
606 static short booleanToShort(boolean x) {
607 return fromBoolean(x);
608 }
609 static char booleanToChar(boolean x) {
610 return (char)fromBoolean(x);
611 }
612 static byte booleanToByte(boolean x) {
613 return fromBoolean(x);
614 }
615
616 // helpers to force boolean into the conversion scheme:
617 static boolean toBoolean(byte x) {
618 // see javadoc for MethodHandles.explicitCastArguments
619 return ((x & 1) != 0);
620 }
621 static byte fromBoolean(boolean x) {
622 // see javadoc for MethodHandles.explicitCastArguments
623 return (x ? (byte)1 : (byte)0);
624 }
625
626 private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
627
628 public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
629 WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
630 MethodHandle mh = cache.get(wdst);
631 if (mh != null) {
632 return mh;
633 }
634 // slow path
635 Class<?> src = wsrc.primitiveType();
636 Class<?> dst = wdst.primitiveType();
637 MethodType type = MethodType.methodType(dst, src);
638 if (wsrc == wdst) {
639 mh = MethodHandles.identity(src);
640 } else {
641 assert(src.isPrimitive() && dst.isPrimitive());
642 try {
643 mh = IMPL_LOOKUP.findStatic(THIS_CLASS, src.getSimpleName()+"To"+capitalize(dst.getSimpleName()), type);
644 } catch (ReflectiveOperationException ex) {
645 mh = null;
646 }
|
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.invoke.MethodHandle;
29 import java.lang.invoke.MethodHandles;
30 import java.lang.invoke.MethodHandles.Lookup;
31 import java.lang.invoke.MethodType;
32 import jdk.internal.vm.annotation.Stable;
33
34 public class ValueConversions {
35 private static final Class<?> THIS_CLASS = ValueConversions.class;
36 private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
37
38 /**
39 * Thread-safe canonicalized mapping from Wrapper to MethodHandle
40 * with unsynchronized reads and synchronized writes.
41 * It's safe to publish MethodHandles by data race because they are immutable.
42 */
43 private static class WrapperCache {
44 @Stable
45 private final MethodHandle[] map = new MethodHandle[Wrapper.COUNT];
46
47 public MethodHandle get(Wrapper w) {
48 return map[w.ordinal()];
49 }
50 public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
51 MethodHandle prev = map[w.ordinal()];
52 if (prev != null) {
53 return prev;
54 } else {
55 map[w.ordinal()] = mh;
56 return mh;
57 }
58 }
59 }
60
61 private static WrapperCache[] newWrapperCaches(int n) {
62 WrapperCache[] caches = new WrapperCache[n];
63 for (int i = 0; i < n; i++)
64 caches[i] = new WrapperCache();
65 return caches;
66 }
67
68 /// Converting references to values.
69
70 // There are several levels of this unboxing conversions:
71 // no conversions: exactly Integer.valueOf, etc.
72 // implicit conversions sanctioned by JLS 5.1.2, etc.
73 // explicit conversions as allowed by explicitCastArguments
74
75 static int unboxInteger(Integer x) {
76 return x;
77 }
78 static int unboxInteger(Object x, boolean cast) {
79 if (x instanceof Integer)
611 static short booleanToShort(boolean x) {
612 return fromBoolean(x);
613 }
614 static char booleanToChar(boolean x) {
615 return (char)fromBoolean(x);
616 }
617 static byte booleanToByte(boolean x) {
618 return fromBoolean(x);
619 }
620
621 // helpers to force boolean into the conversion scheme:
622 static boolean toBoolean(byte x) {
623 // see javadoc for MethodHandles.explicitCastArguments
624 return ((x & 1) != 0);
625 }
626 static byte fromBoolean(boolean x) {
627 // see javadoc for MethodHandles.explicitCastArguments
628 return (x ? (byte)1 : (byte)0);
629 }
630
631 private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.COUNT);
632
633 public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
634 WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
635 MethodHandle mh = cache.get(wdst);
636 if (mh != null) {
637 return mh;
638 }
639 // slow path
640 Class<?> src = wsrc.primitiveType();
641 Class<?> dst = wdst.primitiveType();
642 MethodType type = MethodType.methodType(dst, src);
643 if (wsrc == wdst) {
644 mh = MethodHandles.identity(src);
645 } else {
646 assert(src.isPrimitive() && dst.isPrimitive());
647 try {
648 mh = IMPL_LOOKUP.findStatic(THIS_CLASS, src.getSimpleName()+"To"+capitalize(dst.getSimpleName()), type);
649 } catch (ReflectiveOperationException ex) {
650 mh = null;
651 }
|