Test6998541.java revision 4183:4732a76af216
1189251Ssam/*
2189251Ssam * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3189251Ssam * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4189251Ssam *
5252726Srpaulo * This code is free software; you can redistribute it and/or modify it
6252726Srpaulo * under the terms of the GNU General Public License version 2 only, as
7189251Ssam * published by the Free Software Foundation.
8189251Ssam *
9189251Ssam * This code is distributed in the hope that it will be useful, but WITHOUT
10189251Ssam * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11189251Ssam * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12214734Srpaulo * version 2 for more details (a copy is included in the LICENSE file that
13214734Srpaulo * accompanied this code).
14214734Srpaulo *
15214734Srpaulo * You should have received a copy of the GNU General Public License version
16214734Srpaulo * 2 along with this work; if not, write to the Free Software Foundation,
17252726Srpaulo * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18189251Ssam *
19189251Ssam * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20189251Ssam * or visit www.oracle.com if you need additional information or have any
21189251Ssam * questions.
22189251Ssam *
23189251Ssam */
24189251Ssam
25189251Ssam/**
26189251Ssam * @test
27189251Ssam * @bug 6998541
28189251Ssam * @summary JSR 292 implement missing return-type conversion for OP_RETYPE_RAW
29189251Ssam *
30189251Ssam * @run main/othervm -Xbatch
31189251Ssam *    -XX:+UnlockDiagnosticVMOptions -XX:ScavengeRootsInCode=2
32189251Ssam *       -DTest6998541.N=100000 -DTest6998541.KIND=cast Test6998541
33189251Ssam * @run main/othervm -Xbatch
34189251Ssam *    -XX:+UnlockDiagnosticVMOptions -XX:ScavengeRootsInCode=2
35189251Ssam *       -DTest6998541.N=100000 -DTest6998541.KIND=normal Test6998541
36189251Ssam */
37189251Ssam
38189251Ssamimport java.util.*;
39189251Ssam
40189251Ssamimport java.lang.invoke.*;
41189251Ssamimport static java.lang.invoke.MethodHandles.*;
42189251Ssam
43189251Ssampublic class Test6998541 {
44189251Ssam    private static final Class  CLASS = Test6998541.class;
45189251Ssam    private static final String NAME  = "identity";
46189251Ssam    private static final int    N     = Math.max(2, Integer.getInteger(CLASS.getSimpleName()+".N", 10000));
47189251Ssam    private static final String KIND  = System.getProperty(CLASS.getSimpleName()+".KIND", "cast");
48189251Ssam    private static final int    BITS  = 0x00000201;
49189251Ssam
50189251Ssam    private static final boolean DO_CASTS = !KIND.equals("normal");
51189251Ssam
52189251Ssam    public static void main(String[] args) throws Throwable {
53189251Ssam        System.out.println("KIND="+KIND+" DO_CASTS="+DO_CASTS+" N="+N);
54189251Ssam        doboolean();
55189251Ssam        dobyte();
56189251Ssam        dochar();
57189251Ssam        doshort();
58189251Ssam        doint();
59189251Ssam        dolong();
60189251Ssam        dofloat();
61189251Ssam        dodouble();
62189251Ssam        dovoid();
63189251Ssam    }
64189251Ssam
65189251Ssam    private static void doboolean() throws Throwable {
66189251Ssam        for (int i = 0; i < N; i++) {
67189251Ssam            boolean2prim(false);
68189251Ssam            boolean2prim(true);
69189251Ssam        }
70189251Ssam        boolean2prim_invalid(true);
71189251Ssam    }
72189251Ssam    private static void dobyte() throws Throwable {
73189251Ssam        byte x = Byte.MIN_VALUE;
74189251Ssam        for (int i = 0; i < N; i++, x++)
75189251Ssam            byte2prim(x);
76189251Ssam        byte2prim_invalid(x);
77189251Ssam    }
78189251Ssam    private static void dochar() throws Throwable {
79189251Ssam        char x = Character.MIN_VALUE;
80189251Ssam        for (int i = 0; i < N; i++, x++)
81189251Ssam            char2prim(x);
82189251Ssam        char2prim_invalid(x);
83189251Ssam    }
84189251Ssam    private static void doshort() throws Throwable {
85189251Ssam        short x = Short.MIN_VALUE;
86189251Ssam        for (int i = 0; i < N; i++, x++)
87189251Ssam            short2prim(x);
88189251Ssam        short2prim_invalid(x);
89189251Ssam    }
90189251Ssam    private static void doint() throws Throwable {
91189251Ssam        int x = Integer.MIN_VALUE;
92189251Ssam        int D = Integer.MAX_VALUE / (N / 2) | BITS;
93189251Ssam        for (int i = 0; i < N; i++, x += D) {
94189251Ssam            int2prim(x);
95189251Ssam        }
96189251Ssam        int2prim_invalid(x);
97189251Ssam    }
98189251Ssam    private static void dolong() throws Throwable {
99189251Ssam        long x = Long.MIN_VALUE;
100189251Ssam        long D = Long.MAX_VALUE / ((long) (N / 2)) | BITS;
101189251Ssam        for (int i = 0; i < N; i++, x += D)
102189251Ssam            long2prim(x);
103189251Ssam        long2prim_invalid(x);
104189251Ssam    }
105189251Ssam    private static void dofloat() throws Throwable {
106189251Ssam        float x = Float.MIN_VALUE;
107189251Ssam        float D = Float.MAX_VALUE / ((float) (N / 2));
108189251Ssam        for (int i = 0; i < N; i++, x += D)
109189251Ssam            float2prim(x);
110189251Ssam        float2prim_invalid(x);
111189251Ssam    }
112189251Ssam    private static void dodouble() throws Throwable {
113189251Ssam        double x = Double.MIN_VALUE;
114189251Ssam        double D = Double.MAX_VALUE / ((double) (N / 2));
115189251Ssam        for (int i = 0; i < N; i++, x += D)
116189251Ssam            double2prim(x);
117189251Ssam        double2prim_invalid(x);
118189251Ssam    }
119189251Ssam    private static void dovoid() throws Throwable {
120189251Ssam        for (int i = 0; i < N; i++) {
121189251Ssam            void2prim(i);
122189251Ssam        }
123189251Ssam        void2prim_invalid(0);
124189251Ssam        // do the other direction here also:
125189251Ssam        for (int i = 0; i < N; i++) {
126189251Ssam            prim2void(i);
127189251Ssam        }
128189251Ssam        prim2void_invalid(0);
129189251Ssam    }
130189251Ssam
131189251Ssam    private static void assertEquals(Object o, Object o2) {
132189251Ssam        if (!o.equals(o2))
133189251Ssam            throw new AssertionError("expected: " + o + ", found: " + o2);
134189251Ssam    }
135189251Ssam    private static void fail() {
136189251Ssam        throw new AssertionError();
137189251Ssam    }
138189251Ssam
139189251Ssam    private final static MethodHandles.Lookup lookup = MethodHandles.lookup();
140189251Ssam
141189251Ssam    private static MethodHandle mh(Class ret, Class... args) {
142189251Ssam        try {
143189251Ssam            MethodType mt  = MethodType.methodType(ret, args);
144189251Ssam            Class lookupRet = (args.length == 0 ? void.class : args[0]);
145189251Ssam            MethodHandle mh = lookup.findStatic(CLASS, NAME, mt.changeReturnType(lookupRet));
146189251Ssam            if (DO_CASTS)
147189251Ssam                return MethodHandles.explicitCastArguments(mh, mt);
148189251Ssam            if (canDoAsType(mh.type(), mt))
149189251Ssam                return mh.asType(mt);
150189251Ssam            try {
151189251Ssam                mh.asType(mt);
152189251Ssam                throw new AssertionError("asType should not succeed: "+mh+" => "+mt);
153189251Ssam            } catch (WrongMethodTypeException ex) {
154189251Ssam                // this was a required WMTE
155189251Ssam                return mh.asType(mt.generic()).asType(mt);
156189251Ssam            }
157189251Ssam        } catch (ReflectiveOperationException e) {
158189251Ssam            throw new RuntimeException(e);
159189251Ssam        }
160189251Ssam    }
161189251Ssam    private static final Class<?>[] NUMERIC_TYPE_WIDENING_ORDER = {
162189251Ssam        byte.class, short.class, int.class, long.class, float.class, double.class
163189251Ssam    };
164189251Ssam    private static boolean canDoAsType(Class<?> src, Class<?> dst) {
165189251Ssam        if (src == dst)  return true;
166189251Ssam        if (dst == void.class)  return true;
167189251Ssam        if (!src.isPrimitive() || !dst.isPrimitive())  return true;
168189251Ssam        // primitive conversion works for asType only when it's widening
169189251Ssam        if (src == boolean.class || dst == boolean.class)  return false;
170189251Ssam        if (dst == char.class)  return false;
171189251Ssam        if (src == char.class)  src = int.class;  // can widen char to int
172189251Ssam        for (Class<?> ntype : NUMERIC_TYPE_WIDENING_ORDER) {
173189251Ssam            if (src == ntype)  return true;
174189251Ssam            if (dst == ntype)  return false;
175189251Ssam        }
176189251Ssam        throw new AssertionError("should not reach here: "+src+", "+dst);
177189251Ssam    }
178189251Ssam    private static boolean canDoAsType(MethodType mt0, MethodType mt1) {
179189251Ssam        Class<?> rt0 = mt0.returnType();
180189251Ssam        Class<?> rt1 = mt1.returnType();
181189251Ssam        if (!canDoAsType(rt0, rt1))  return false;
182189251Ssam        int argc = mt0.parameterCount();
183189251Ssam        if (argc != mt1.parameterCount())  return false;
184189251Ssam        for (int i = 0; i < argc; i++) {
185189251Ssam            if (!canDoAsType(mt1.parameterType(i), mt0.parameterType(i)))
186189251Ssam                return false;
187189251Ssam        }
188189251Ssam        return true;
189189251Ssam    }
190189251Ssam
191189251Ssam    private static MethodHandle mh_z(Class ret) { return mh(ret, boolean.class); }
192189251Ssam
193189251Ssam    private final static MethodHandle mh_zz = mh_z(boolean.class);
194189251Ssam    private final static MethodHandle mh_bz = mh_z(byte.class   );
195189251Ssam    private final static MethodHandle mh_cz = mh_z(char.class   );
196189251Ssam    private final static MethodHandle mh_sz = mh_z(short.class  );
197189251Ssam    private final static MethodHandle mh_iz = mh_z(int.class    );
198189251Ssam    private final static MethodHandle mh_jz = mh_z(long.class   );
199189251Ssam    private final static MethodHandle mh_fz = mh_z(float.class  );
200189251Ssam    private final static MethodHandle mh_dz = mh_z(double.class );
201189251Ssam
202189251Ssam    private static void boolean2prim(boolean x) throws Throwable {
203189251Ssam        int i = x ? 1 : 0;
204189251Ssam        assertEquals(          x, (boolean) mh_zz.invokeExact(x));  // boolean -> boolean
205189251Ssam        if (!DO_CASTS)  return;
206189251Ssam        assertEquals((byte)    i, (byte)    mh_bz.invokeExact(x));  // boolean -> byte
207189251Ssam        assertEquals((char)    i, (char)    mh_cz.invokeExact(x));  // boolean -> char
208189251Ssam        assertEquals((short)   i, (short)   mh_sz.invokeExact(x));  // boolean -> short
209189251Ssam        assertEquals((int)     i, (int)     mh_iz.invokeExact(x));  // boolean -> int
210189251Ssam        assertEquals((long)    i, (long)    mh_jz.invokeExact(x));  // boolean -> long
211189251Ssam        assertEquals((float)   i, (float)   mh_fz.invokeExact(x));  // boolean -> float
212189251Ssam        assertEquals((double)  i, (double)  mh_dz.invokeExact(x));  // boolean -> double
213189251Ssam    }
214189251Ssam    private static void boolean2prim_invalid(boolean x) throws Throwable {
215189251Ssam        if (DO_CASTS)  return;
216189251Ssam        try { byte    y = (byte)    mh_bz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> byte
217189251Ssam        try { char    y = (char)    mh_cz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> char
218189251Ssam        try { short   y = (short)   mh_sz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> short
219189251Ssam        try { int     y = (int)     mh_iz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> int
220189251Ssam        try { long    y = (long)    mh_jz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> long
221189251Ssam        try { float   y = (float)   mh_fz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> float
222189251Ssam        try { double  y = (double)  mh_dz.invokeExact(x); fail(); } catch (ClassCastException _) {}  // boolean -> double
223189251Ssam    }
224189251Ssam
225189251Ssam    private static MethodHandle mh_b(Class ret) { return mh(ret, byte.class); }
226189251Ssam
227189251Ssam    private final static MethodHandle mh_zb = mh_b(boolean.class);
228189251Ssam    private final static MethodHandle mh_bb = mh_b(byte.class   );
229189251Ssam    private final static MethodHandle mh_cb = mh_b(char.class   );
230189251Ssam    private final static MethodHandle mh_sb = mh_b(short.class  );
231214734Srpaulo    private final static MethodHandle mh_ib = mh_b(int.class    );
232189251Ssam    private final static MethodHandle mh_jb = mh_b(long.class   );
233189251Ssam    private final static MethodHandle mh_fb = mh_b(float.class  );
234189251Ssam    private final static MethodHandle mh_db = mh_b(double.class );
235189251Ssam
236189251Ssam    private static void byte2prim(byte x) throws Throwable {
237189251Ssam        assertEquals((byte)    x, (byte)    mh_bb.invokeExact(x));  // byte -> byte
238189251Ssam        assertEquals((short)   x, (short)   mh_sb.invokeExact(x));  // byte -> short
239189251Ssam        assertEquals((int)     x, (int)     mh_ib.invokeExact(x));  // byte -> int
240189251Ssam        assertEquals((long)    x, (long)    mh_jb.invokeExact(x));  // byte -> long
241189251Ssam        assertEquals((float)   x, (float)   mh_fb.invokeExact(x));  // byte -> float
242189251Ssam        assertEquals((double)  x, (double)  mh_db.invokeExact(x));  // byte -> double
243189251Ssam        if (!DO_CASTS)  return;
244189251Ssam        boolean z = ((x & 1) != 0);
245189251Ssam        assertEquals((char)    x, (char)    mh_cb.invokeExact(x));  // byte -> char
246189251Ssam        assertEquals((boolean) z, (boolean) mh_zb.invokeExact(x));  // byte -> boolean
247189251Ssam    }
248189251Ssam    private static void byte2prim_invalid(byte x) throws Throwable {
249189251Ssam        if (DO_CASTS)  return;
250189251Ssam        try { char    y = (char)    mh_cb.invokeExact(x); fail(); } catch (ClassCastException _) {}  // byte -> char
251189251Ssam        try { boolean y = (boolean) mh_zb.invokeExact(x); fail(); } catch (ClassCastException _) {}  // byte -> boolean
252189251Ssam    }
253189251Ssam
254189251Ssam    private static MethodHandle mh_c(Class ret) { return mh(ret, char.class); }
255189251Ssam
256189251Ssam    private final static MethodHandle mh_zc = mh_c(boolean.class);
257189251Ssam    private final static MethodHandle mh_bc = mh_c(byte.class   );
258189251Ssam    private final static MethodHandle mh_cc = mh_c(char.class   );
259189251Ssam    private final static MethodHandle mh_sc = mh_c(short.class  );
260189251Ssam    private final static MethodHandle mh_ic = mh_c(int.class    );
261189251Ssam    private final static MethodHandle mh_jc = mh_c(long.class   );
262189251Ssam    private final static MethodHandle mh_fc = mh_c(float.class  );
263189251Ssam    private final static MethodHandle mh_dc = mh_c(double.class );
264189251Ssam
265189251Ssam    private static void char2prim(char x) throws Throwable {
266189251Ssam        assertEquals((char)    x, (char)    mh_cc.invokeExact(x));  // char -> char
267189251Ssam        assertEquals((int)     x, (int)     mh_ic.invokeExact(x));  // char -> int
268189251Ssam        assertEquals((long)    x, (long)    mh_jc.invokeExact(x));  // char -> long
269189251Ssam        assertEquals((float)   x, (float)   mh_fc.invokeExact(x));  // char -> float
270189251Ssam        assertEquals((double)  x, (double)  mh_dc.invokeExact(x));  // char -> double
271189251Ssam        if (!DO_CASTS)  return;
272189251Ssam        boolean z = ((x & 1) != 0);
273189251Ssam        assertEquals((boolean) z, (boolean) mh_zc.invokeExact(x));  // char -> boolean
274189251Ssam        assertEquals((byte)    x, (byte)    mh_bc.invokeExact(x));  // char -> byte
275189251Ssam        assertEquals((short)   x, (short)   mh_sc.invokeExact(x));  // char -> short
276189251Ssam    }
277189251Ssam    private static void char2prim_invalid(char x) throws Throwable {
278189251Ssam        if (DO_CASTS)  return;
279189251Ssam        try { boolean y = (boolean) mh_zc.invokeExact(x); fail(); } catch (ClassCastException _) {}  // char -> boolean
280189251Ssam        try { byte    y = (byte)    mh_bc.invokeExact(x); fail(); } catch (ClassCastException _) {}  // char -> byte
281189251Ssam        try { short   y = (short)   mh_sc.invokeExact(x); fail(); } catch (ClassCastException _) {}  // char -> short
282189251Ssam    }
283189251Ssam
284189251Ssam    private static MethodHandle mh_s(Class ret) { return mh(ret, short.class); }
285189251Ssam
286189251Ssam    private final static MethodHandle mh_zs = mh_s(boolean.class);
287189251Ssam    private final static MethodHandle mh_bs = mh_s(byte.class   );
288189251Ssam    private final static MethodHandle mh_cs = mh_s(char.class   );
289189251Ssam    private final static MethodHandle mh_ss = mh_s(short.class  );
290189251Ssam    private final static MethodHandle mh_is = mh_s(int.class    );
291189251Ssam    private final static MethodHandle mh_js = mh_s(long.class   );
292189251Ssam    private final static MethodHandle mh_fs = mh_s(float.class  );
293189251Ssam    private final static MethodHandle mh_ds = mh_s(double.class );
294189251Ssam
295189251Ssam    private static void short2prim(short x) throws Throwable {
296189251Ssam        assertEquals((short)   x, (short)   mh_ss.invokeExact(x));  // short -> short
297189251Ssam        assertEquals((int)     x, (int)     mh_is.invokeExact(x));  // short -> int
298189251Ssam        assertEquals((long)    x, (long)    mh_js.invokeExact(x));  // short -> long
299189251Ssam        assertEquals((float)   x, (float)   mh_fs.invokeExact(x));  // short -> float
300189251Ssam        assertEquals((double)  x, (double)  mh_ds.invokeExact(x));  // short -> double
301189251Ssam        if (!DO_CASTS)  return;
302189251Ssam        boolean z = ((x & 1) != 0);
303189251Ssam        assertEquals((boolean) z, (boolean) mh_zs.invokeExact(x));  // short -> boolean
304189251Ssam        assertEquals((byte)    x, (byte)    mh_bs.invokeExact(x));  // short -> byte
305189251Ssam        assertEquals((char)    x, (char)    mh_cs.invokeExact(x));  // short -> char
306189251Ssam    }
307189251Ssam    private static void short2prim_invalid(short x) throws Throwable {
308189251Ssam        if (DO_CASTS)  return;
309189251Ssam        try { boolean y = (boolean) mh_zs.invokeExact(x); fail(); } catch (ClassCastException _) {}  // short -> boolean
310189251Ssam        try { byte    y = (byte)    mh_bs.invokeExact(x); fail(); } catch (ClassCastException _) {}  // short -> byte
311189251Ssam        try { char    y = (char)    mh_cs.invokeExact(x); fail(); } catch (ClassCastException _) {}  // short -> char
312189251Ssam    }
313189251Ssam
314189251Ssam    private static MethodHandle mh_i(Class ret) { return mh(ret, int.class); }
315189251Ssam
316189251Ssam    private final static MethodHandle mh_zi = mh_i(boolean.class);
317189251Ssam    private final static MethodHandle mh_bi = mh_i(byte.class   );
318189251Ssam    private final static MethodHandle mh_ci = mh_i(char.class   );
319189251Ssam    private final static MethodHandle mh_si = mh_i(short.class  );
320189251Ssam    private final static MethodHandle mh_ii = mh_i(int.class    );
321189251Ssam    private final static MethodHandle mh_ji = mh_i(long.class   );
322189251Ssam    private final static MethodHandle mh_fi = mh_i(float.class  );
323189251Ssam    private final static MethodHandle mh_di = mh_i(double.class );
324189251Ssam
325189251Ssam    private static void int2prim(int x) throws Throwable {
326189251Ssam        assertEquals((int)     x, (int)     mh_ii.invokeExact(x));  // int -> int
327189251Ssam        assertEquals((long)    x, (long)    mh_ji.invokeExact(x));  // int -> long
328189251Ssam        assertEquals((float)   x, (float)   mh_fi.invokeExact(x));  // int -> float
329189251Ssam        assertEquals((double)  x, (double)  mh_di.invokeExact(x));  // int -> double
330189251Ssam        if (!DO_CASTS)  return;
331189251Ssam        boolean z = ((x & 1) != 0);
332189251Ssam        assertEquals((boolean) z, (boolean) mh_zi.invokeExact(x));  // int -> boolean
333189251Ssam        assertEquals((byte)    x, (byte)    mh_bi.invokeExact(x));  // int -> byte
334189251Ssam        assertEquals((char)    x, (char)    mh_ci.invokeExact(x));  // int -> char
335189251Ssam        assertEquals((short)   x, (short)   mh_si.invokeExact(x));  // int -> short
336189251Ssam    }
337189251Ssam    private static void int2prim_invalid(int x) throws Throwable {
338189251Ssam        if (DO_CASTS)  return;
339189251Ssam        try { boolean y = (boolean) mh_zi.invokeExact(x); fail(); } catch (ClassCastException _) {}  // int -> boolean
340189251Ssam        try { byte    y = (byte)    mh_bi.invokeExact(x); fail(); } catch (ClassCastException _) {}  // int -> byte
341189251Ssam        try { char    y = (char)    mh_ci.invokeExact(x); fail(); } catch (ClassCastException _) {}  // int -> char
342189251Ssam        try { short   y = (short)   mh_si.invokeExact(x); fail(); } catch (ClassCastException _) {}  // int -> short
343189251Ssam    }
344189251Ssam
345189251Ssam    private static MethodHandle mh_j(Class ret) { return mh(ret, long.class); }
346189251Ssam
347189251Ssam    private final static MethodHandle mh_zj = mh_j(boolean.class);
348189251Ssam    private final static MethodHandle mh_bj = mh_j(byte.class   );
349189251Ssam    private final static MethodHandle mh_cj = mh_j(char.class   );
350189251Ssam    private final static MethodHandle mh_sj = mh_j(short.class  );
351189251Ssam    private final static MethodHandle mh_ij = mh_j(int.class    );
352189251Ssam    private final static MethodHandle mh_jj = mh_j(long.class   );
353189251Ssam    private final static MethodHandle mh_fj = mh_j(float.class  );
354189251Ssam    private final static MethodHandle mh_dj = mh_j(double.class );
355189251Ssam
356189251Ssam    private static void long2prim(long x) throws Throwable {
357189251Ssam        assertEquals((long)   x, (long)    mh_jj.invokeExact(x));  // long -> long
358189251Ssam        assertEquals((float)  x, (float)   mh_fj.invokeExact(x));  // long -> float
359189251Ssam        assertEquals((double) x, (double)  mh_dj.invokeExact(x));  // long -> double
360189251Ssam        if (!DO_CASTS)  return;
361189251Ssam        boolean z = ((x & 1) != 0);
362189251Ssam        assertEquals((boolean)z, (boolean) mh_zj.invokeExact(x));  // long -> boolean
363189251Ssam        assertEquals((byte)   x, (byte)    mh_bj.invokeExact(x));  // long -> byte
364189251Ssam        assertEquals((char)   x, (char)    mh_cj.invokeExact(x));  // long -> char
365189251Ssam        assertEquals((short)  x, (short)   mh_sj.invokeExact(x));  // long -> short
366189251Ssam        assertEquals((int)    x, (int)     mh_ij.invokeExact(x));  // long -> int
367189251Ssam    }
368189251Ssam    private static void long2prim_invalid(long x) throws Throwable {
369189251Ssam        if (DO_CASTS)  return;
370189251Ssam        try { boolean y = (boolean) mh_zj.invokeExact(x); fail(); } catch (ClassCastException _) {}  // long -> boolean
371189251Ssam        try { byte    y = (byte)    mh_bj.invokeExact(x); fail(); } catch (ClassCastException _) {}  // long -> byte
372189251Ssam        try { char    y = (char)    mh_cj.invokeExact(x); fail(); } catch (ClassCastException _) {}  // long -> char
373189251Ssam        try { short   y = (short)   mh_sj.invokeExact(x); fail(); } catch (ClassCastException _) {}  // long -> short
374189251Ssam        try { int     y = (int)     mh_ij.invokeExact(x); fail(); } catch (ClassCastException _) {}  // long -> int
375189251Ssam    }
376189251Ssam
377189251Ssam    private static MethodHandle mh_f(Class ret) { return mh(ret, float.class); }
378189251Ssam
379189251Ssam    private final static MethodHandle mh_zf = mh_f(boolean.class);
380189251Ssam    private final static MethodHandle mh_bf = mh_f(byte.class   );
381189251Ssam    private final static MethodHandle mh_cf = mh_f(char.class   );
382189251Ssam    private final static MethodHandle mh_sf = mh_f(short.class  );
383189251Ssam    private final static MethodHandle mh_if = mh_f(int.class    );
384189251Ssam    private final static MethodHandle mh_jf = mh_f(long.class   );
385189251Ssam    private final static MethodHandle mh_ff = mh_f(float.class  );
386189251Ssam    private final static MethodHandle mh_df = mh_f(double.class );
387189251Ssam
388189251Ssam    private static void float2prim(float x) throws Throwable {
389189251Ssam        assertEquals((float)   x, (float)   mh_ff.invokeExact(x));  // float -> float
390189251Ssam        assertEquals((double)  x, (double)  mh_df.invokeExact(x));  // float -> double
391189251Ssam        if (!DO_CASTS)  return;
392189251Ssam        boolean z = (((byte) x & 1) != 0);
393189251Ssam        assertEquals((boolean) z, (boolean) mh_zf.invokeExact(x));  // float -> boolean
394189251Ssam        assertEquals((byte)    x, (byte)    mh_bf.invokeExact(x));  // float -> byte
395189251Ssam        assertEquals((char)    x, (char)    mh_cf.invokeExact(x));  // float -> char
396189251Ssam        assertEquals((short)   x, (short)   mh_sf.invokeExact(x));  // float -> short
397189251Ssam        assertEquals((int)     x, (int)     mh_if.invokeExact(x));  // float -> int
398189251Ssam        assertEquals((long)    x, (long)    mh_jf.invokeExact(x));  // float -> long
399189251Ssam    }
400189251Ssam    private static void float2prim_invalid(float x) throws Throwable {
401189251Ssam        if (DO_CASTS)  return;
402189251Ssam        try { boolean y = (boolean) mh_zf.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> boolean
403189251Ssam        try { byte    y = (byte)    mh_bf.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> byte
404189251Ssam        try { char    y = (char)    mh_cf.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> char
405189251Ssam        try { short   y = (short)   mh_sf.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> short
406189251Ssam        try { int     y = (int)     mh_if.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> int
407189251Ssam        try { long    y = (long)    mh_jf.invokeExact(x); fail(); } catch (ClassCastException _) {}  // float -> long
408189251Ssam    }
409189251Ssam
410189251Ssam    private static MethodHandle mh_d(Class ret) { return mh(ret, double.class); }
411189251Ssam
412189251Ssam    private final static MethodHandle mh_zd = mh_d(boolean.class);
413189251Ssam    private final static MethodHandle mh_bd = mh_d(byte.class   );
414189251Ssam    private final static MethodHandle mh_cd = mh_d(char.class   );
415189251Ssam    private final static MethodHandle mh_sd = mh_d(short.class  );
416189251Ssam    private final static MethodHandle mh_id = mh_d(int.class    );
417189251Ssam    private final static MethodHandle mh_jd = mh_d(long.class   );
418189251Ssam    private final static MethodHandle mh_fd = mh_d(float.class  );
419189251Ssam    private final static MethodHandle mh_dd = mh_d(double.class );
420189251Ssam
421189251Ssam    private static void double2prim(double x) throws Throwable {
422189251Ssam        assertEquals((double) x, (double)  mh_dd.invokeExact(x));  // double -> double
423189251Ssam        if (!DO_CASTS)  return;
424189251Ssam        boolean z = (((byte) x & 1) != 0);
425189251Ssam        assertEquals((boolean) z, (boolean) mh_zd.invokeExact(x));  // double -> boolean
426189251Ssam        assertEquals((byte)    x, (byte)    mh_bd.invokeExact(x));  // double -> byte
427189251Ssam        assertEquals((char)    x, (char)    mh_cd.invokeExact(x));  // double -> char
428189251Ssam        assertEquals((short)   x, (short)   mh_sd.invokeExact(x));  // double -> short
429189251Ssam        assertEquals((int)     x, (int)     mh_id.invokeExact(x));  // double -> int
430189251Ssam        assertEquals((long)    x, (long)    mh_jd.invokeExact(x));  // double -> long
431189251Ssam        assertEquals((float)   x, (float)   mh_fd.invokeExact(x));  // double -> float
432189251Ssam    }
433189251Ssam    private static void double2prim_invalid(double x) throws Throwable {
434189251Ssam        if (DO_CASTS)  return;
435189251Ssam        try { boolean y = (boolean) mh_zd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> boolean
436189251Ssam        try { byte    y = (byte)    mh_bd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> byte
437189251Ssam        try { char    y = (char)    mh_cd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> char
438189251Ssam        try { short   y = (short)   mh_sd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> short
439189251Ssam        try { int     y = (int)     mh_id.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> int
440189251Ssam        try { long    y = (long)    mh_jd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> long
441189251Ssam        try { float   y = (float)   mh_fd.invokeExact(x); fail(); } catch (ClassCastException _) {}  // double -> float
442189251Ssam    }
443189251Ssam
444189251Ssam    private final static MethodHandle mh_zv = mh(boolean.class);
445189251Ssam    private final static MethodHandle mh_bv = mh(byte.class   );
446189251Ssam    private final static MethodHandle mh_cv = mh(char.class   );
447189251Ssam    private final static MethodHandle mh_sv = mh(short.class  );
448189251Ssam    private final static MethodHandle mh_iv = mh(int.class    );
449189251Ssam    private final static MethodHandle mh_jv = mh(long.class   );
450189251Ssam    private final static MethodHandle mh_fv = mh(float.class  );
451189251Ssam    private final static MethodHandle mh_dv = mh(double.class );
452189251Ssam
453189251Ssam    private static void void2prim(int i) throws Throwable {
454189251Ssam        if (!DO_CASTS)  return;
455189251Ssam        assertEquals(        false, (boolean) mh_zv.invokeExact());  // void -> boolean
456189251Ssam        assertEquals((byte)  0,     (byte)    mh_bv.invokeExact());  // void -> byte
457189251Ssam        assertEquals((char)  0,     (char)    mh_cv.invokeExact());  // void -> char
458189251Ssam        assertEquals((short) 0,     (short)   mh_sv.invokeExact());  // void -> short
459189251Ssam        assertEquals(        0,     (int)     mh_iv.invokeExact());  // void -> int
460189251Ssam        assertEquals(        0L,    (long)    mh_jv.invokeExact());  // void -> long
461189251Ssam        assertEquals(        0.0f,  (float)   mh_fv.invokeExact());  // void -> float
462189251Ssam        assertEquals(        0.0d,  (double)  mh_dv.invokeExact());  // void -> double
463189251Ssam    }
464189251Ssam
465189251Ssam    private static void void2prim_invalid(double x) throws Throwable {
466189251Ssam        if (DO_CASTS)  return;
467189251Ssam        try { assertEquals(        false, (boolean) mh_zv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> boolean
468189251Ssam        try { assertEquals((byte)  0,     (byte)    mh_bv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> byte
469189251Ssam        try { assertEquals((char)  0,     (char)    mh_cv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> char
470189251Ssam        try { assertEquals((short) 0,     (short)   mh_sv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> short
471189251Ssam        try { assertEquals(        0,     (int)     mh_iv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> int
472189251Ssam        try { assertEquals(        0L,    (long)    mh_jv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> long
473189251Ssam        try { assertEquals(        0.0f,  (float)   mh_fv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> float
474189251Ssam        try { assertEquals(        0.0d,  (double)  mh_dv.invokeExact()); fail(); } catch (NullPointerException _) {}  // void -> double
475189251Ssam    }
476189251Ssam
477189251Ssam    private static MethodHandle mh_v(Class arg) { return mh(void.class, arg); }
478189251Ssam
479189251Ssam    private final static MethodHandle mh_vz = mh_v(boolean.class);
480189251Ssam    private final static MethodHandle mh_vb = mh_v(byte.class   );
481189251Ssam    private final static MethodHandle mh_vc = mh_v(char.class   );
482189251Ssam    private final static MethodHandle mh_vs = mh_v(short.class  );
483189251Ssam    private final static MethodHandle mh_vi = mh_v(int.class    );
484189251Ssam    private final static MethodHandle mh_vj = mh_v(long.class   );
485189251Ssam    private final static MethodHandle mh_vf = mh_v(float.class  );
486189251Ssam    private final static MethodHandle mh_vd = mh_v(double.class );
487189251Ssam
488189251Ssam    private static void prim2void(int x) throws Throwable {
489189251Ssam        boolean z = ((x & 1) != 0);
490189251Ssam        mh_vz.invokeExact(         z);  // boolean -> void
491189251Ssam        mh_vb.invokeExact((byte)   x);  // byte    -> void
492189251Ssam        mh_vc.invokeExact((char)   x);  // char    -> void
493189251Ssam        mh_vs.invokeExact((short)  x);  // short   -> void
494214734Srpaulo        mh_vi.invokeExact((int)    x);  // int     -> void
495189251Ssam        mh_vj.invokeExact((long)   x);  // long    -> void
496189251Ssam        mh_vf.invokeExact((float)  x);  // float   -> void
497189251Ssam        mh_vd.invokeExact((double) x);  // double  -> void
498189251Ssam    }
499189251Ssam
500189251Ssam    private static void prim2void_invalid(int x) throws Throwable {
501189251Ssam        // no cases
502189251Ssam    }
503189251Ssam
504189251Ssam    private static boolean identity(boolean v) { return v; }
505189251Ssam    private static byte    identity(byte    v) { return v; }
506189251Ssam    private static char    identity(char    v) { return v; }
507189251Ssam    private static short   identity(short   v) { return v; }
508189251Ssam    private static int     identity(int     v) { return v; }
509189251Ssam    private static long    identity(long    v) { return v; }
510189251Ssam    private static float   identity(float   v) { return v; }
511189251Ssam    private static double  identity(double  v) { return v; }
512189251Ssam    private static void    identity() {}
513189251Ssam}
514189251Ssam