1/*
2 * Copyright (c) 2011, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 6998541
27 * @summary JSR 292 implement missing return-type conversion for OP_RETYPE_RAW
28 *
29 * @run main/othervm -Xbatch
30 *    -XX:+UnlockDiagnosticVMOptions -XX:ScavengeRootsInCode=2
31 *       -DTest6998541.N=100000 -DTest6998541.KIND=cast Test6998541
32 * @run main/othervm -Xbatch
33 *    -XX:+UnlockDiagnosticVMOptions -XX:ScavengeRootsInCode=2
34 *       -DTest6998541.N=100000 -DTest6998541.KIND=normal Test6998541
35 */
36
37import java.util.*;
38
39import java.lang.invoke.*;
40import static java.lang.invoke.MethodHandles.*;
41
42public class Test6998541 {
43    private static final Class  CLASS = Test6998541.class;
44    private static final String NAME  = "identity";
45    private static final int    N     = Math.max(2, Integer.getInteger(CLASS.getSimpleName()+".N", 10000));
46    private static final String KIND  = System.getProperty(CLASS.getSimpleName()+".KIND", "cast");
47    private static final int    BITS  = 0x00000201;
48
49    private static final boolean DO_CASTS = !KIND.equals("normal");
50
51    public static void main(String[] args) throws Throwable {
52        System.out.println("KIND="+KIND+" DO_CASTS="+DO_CASTS+" N="+N);
53        doboolean();
54        dobyte();
55        dochar();
56        doshort();
57        doint();
58        dolong();
59        dofloat();
60        dodouble();
61        dovoid();
62    }
63
64    private static void doboolean() throws Throwable {
65        for (int i = 0; i < N; i++) {
66            boolean2prim(false);
67            boolean2prim(true);
68        }
69        boolean2prim_invalid(true);
70    }
71    private static void dobyte() throws Throwable {
72        byte x = Byte.MIN_VALUE;
73        for (int i = 0; i < N; i++, x++)
74            byte2prim(x);
75        byte2prim_invalid(x);
76    }
77    private static void dochar() throws Throwable {
78        char x = Character.MIN_VALUE;
79        for (int i = 0; i < N; i++, x++)
80            char2prim(x);
81        char2prim_invalid(x);
82    }
83    private static void doshort() throws Throwable {
84        short x = Short.MIN_VALUE;
85        for (int i = 0; i < N; i++, x++)
86            short2prim(x);
87        short2prim_invalid(x);
88    }
89    private static void doint() throws Throwable {
90        int x = Integer.MIN_VALUE;
91        int D = Integer.MAX_VALUE / (N / 2) | BITS;
92        for (int i = 0; i < N; i++, x += D) {
93            int2prim(x);
94        }
95        int2prim_invalid(x);
96    }
97    private static void dolong() throws Throwable {
98        long x = Long.MIN_VALUE;
99        long D = Long.MAX_VALUE / ((long) (N / 2)) | BITS;
100        for (int i = 0; i < N; i++, x += D)
101            long2prim(x);
102        long2prim_invalid(x);
103    }
104    private static void dofloat() throws Throwable {
105        float x = Float.MIN_VALUE;
106        float D = Float.MAX_VALUE / ((float) (N / 2));
107        for (int i = 0; i < N; i++, x += D)
108            float2prim(x);
109        float2prim_invalid(x);
110    }
111    private static void dodouble() throws Throwable {
112        double x = Double.MIN_VALUE;
113        double D = Double.MAX_VALUE / ((double) (N / 2));
114        for (int i = 0; i < N; i++, x += D)
115            double2prim(x);
116        double2prim_invalid(x);
117    }
118    private static void dovoid() throws Throwable {
119        for (int i = 0; i < N; i++) {
120            void2prim(i);
121        }
122        void2prim_invalid(0);
123        // do the other direction here also:
124        for (int i = 0; i < N; i++) {
125            prim2void(i);
126        }
127        prim2void_invalid(0);
128    }
129
130    private static void assertEquals(Object o, Object o2) {
131        if (!o.equals(o2))
132            throw new AssertionError("expected: " + o + ", found: " + o2);
133    }
134    private static void fail() {
135        throw new AssertionError();
136    }
137
138    private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
139
140    private static MethodHandle mh(Class ret, Class... args) {
141        try {
142            MethodType mt  = MethodType.methodType(ret, args);
143            Class lookupRet = (args.length == 0 ? void.class : args[0]);
144            MethodHandle mh = lookup.findStatic(CLASS, NAME, mt.changeReturnType(lookupRet));
145            if (DO_CASTS)
146                return MethodHandles.explicitCastArguments(mh, mt);
147            if (canDoAsType(mh.type(), mt))
148                return mh.asType(mt);
149            try {
150                mh.asType(mt);
151                throw new AssertionError("asType should not succeed: "+mh+" => "+mt);
152            } catch (WrongMethodTypeException ex) {
153                // this was a required WMTE
154                return mh.asType(mt.generic()).asType(mt);
155            }
156        } catch (ReflectiveOperationException e) {
157            throw new RuntimeException(e);
158        }
159    }
160    private static final Class<?>[] NUMERIC_TYPE_WIDENING_ORDER = {
161        byte.class, short.class, int.class, long.class, float.class, double.class
162    };
163    private static boolean canDoAsType(Class<?> src, Class<?> dst) {
164        if (src == dst)  return true;
165        if (dst == void.class)  return true;
166        if (src == void.class)  return true;  // allow void->zero
167        if (!src.isPrimitive() || !dst.isPrimitive())  return true;
168        // primitive conversion works for asType only when it's widening
169        if (src == boolean.class || dst == boolean.class)  return false;
170        if (dst == char.class)  return false;
171        if (src == char.class)  src = int.class;  // can widen char to int
172        for (Class<?> ntype : NUMERIC_TYPE_WIDENING_ORDER) {
173            if (src == ntype)  return true;
174            if (dst == ntype)  return false;
175        }
176        throw new AssertionError("should not reach here: "+src+", "+dst);
177    }
178    private static boolean canDoAsType(MethodType mt0, MethodType mt1) {
179        Class<?> rt0 = mt0.returnType();
180        Class<?> rt1 = mt1.returnType();
181        if (!canDoAsType(rt0, rt1))  return false;
182        int argc = mt0.parameterCount();
183        if (argc != mt1.parameterCount())  return false;
184        for (int i = 0; i < argc; i++) {
185            if (!canDoAsType(mt1.parameterType(i), mt0.parameterType(i)))
186                return false;
187        }
188        return true;
189    }
190
191    private static MethodHandle mh_z(Class ret) { return mh(ret, boolean.class); }
192
193    private static final MethodHandle mh_zz = mh_z(boolean.class);
194    private static final MethodHandle mh_bz = mh_z(byte.class   );
195    private static final MethodHandle mh_cz = mh_z(char.class   );
196    private static final MethodHandle mh_sz = mh_z(short.class  );
197    private static final MethodHandle mh_iz = mh_z(int.class    );
198    private static final MethodHandle mh_jz = mh_z(long.class   );
199    private static final MethodHandle mh_fz = mh_z(float.class  );
200    private static final MethodHandle mh_dz = mh_z(double.class );
201
202    private static void boolean2prim(boolean x) throws Throwable {
203        int i = x ? 1 : 0;
204        assertEquals(          x, (boolean) mh_zz.invokeExact(x));  // boolean -> boolean
205        if (!DO_CASTS)  return;
206        assertEquals((byte)    i, (byte)    mh_bz.invokeExact(x));  // boolean -> byte
207        assertEquals((char)    i, (char)    mh_cz.invokeExact(x));  // boolean -> char
208        assertEquals((short)   i, (short)   mh_sz.invokeExact(x));  // boolean -> short
209        assertEquals((int)     i, (int)     mh_iz.invokeExact(x));  // boolean -> int
210        assertEquals((long)    i, (long)    mh_jz.invokeExact(x));  // boolean -> long
211        assertEquals((float)   i, (float)   mh_fz.invokeExact(x));  // boolean -> float
212        assertEquals((double)  i, (double)  mh_dz.invokeExact(x));  // boolean -> double
213    }
214    private static void boolean2prim_invalid(boolean x) throws Throwable {
215        if (DO_CASTS)  return;
216        try { byte    y = (byte)    mh_bz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> byte
217        try { char    y = (char)    mh_cz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> char
218        try { short   y = (short)   mh_sz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> short
219        try { int     y = (int)     mh_iz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> int
220        try { long    y = (long)    mh_jz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> long
221        try { float   y = (float)   mh_fz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> float
222        try { double  y = (double)  mh_dz.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // boolean -> double
223    }
224
225    private static MethodHandle mh_b(Class ret) { return mh(ret, byte.class); }
226
227    private static final MethodHandle mh_zb = mh_b(boolean.class);
228    private static final MethodHandle mh_bb = mh_b(byte.class   );
229    private static final MethodHandle mh_cb = mh_b(char.class   );
230    private static final MethodHandle mh_sb = mh_b(short.class  );
231    private static final MethodHandle mh_ib = mh_b(int.class    );
232    private static final MethodHandle mh_jb = mh_b(long.class   );
233    private static final MethodHandle mh_fb = mh_b(float.class  );
234    private static final MethodHandle mh_db = mh_b(double.class );
235
236    private static void byte2prim(byte x) throws Throwable {
237        assertEquals((byte)    x, (byte)    mh_bb.invokeExact(x));  // byte -> byte
238        assertEquals((short)   x, (short)   mh_sb.invokeExact(x));  // byte -> short
239        assertEquals((int)     x, (int)     mh_ib.invokeExact(x));  // byte -> int
240        assertEquals((long)    x, (long)    mh_jb.invokeExact(x));  // byte -> long
241        assertEquals((float)   x, (float)   mh_fb.invokeExact(x));  // byte -> float
242        assertEquals((double)  x, (double)  mh_db.invokeExact(x));  // byte -> double
243        if (!DO_CASTS)  return;
244        boolean z = ((x & 1) != 0);
245        assertEquals((char)    x, (char)    mh_cb.invokeExact(x));  // byte -> char
246        assertEquals((boolean) z, (boolean) mh_zb.invokeExact(x));  // byte -> boolean
247    }
248    private static void byte2prim_invalid(byte x) throws Throwable {
249        if (DO_CASTS)  return;
250        try { char    y = (char)    mh_cb.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // byte -> char
251        try { boolean y = (boolean) mh_zb.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // byte -> boolean
252    }
253
254    private static MethodHandle mh_c(Class ret) { return mh(ret, char.class); }
255
256    private static final MethodHandle mh_zc = mh_c(boolean.class);
257    private static final MethodHandle mh_bc = mh_c(byte.class   );
258    private static final MethodHandle mh_cc = mh_c(char.class   );
259    private static final MethodHandle mh_sc = mh_c(short.class  );
260    private static final MethodHandle mh_ic = mh_c(int.class    );
261    private static final MethodHandle mh_jc = mh_c(long.class   );
262    private static final MethodHandle mh_fc = mh_c(float.class  );
263    private static final MethodHandle mh_dc = mh_c(double.class );
264
265    private static void char2prim(char x) throws Throwable {
266        assertEquals((char)    x, (char)    mh_cc.invokeExact(x));  // char -> char
267        assertEquals((int)     x, (int)     mh_ic.invokeExact(x));  // char -> int
268        assertEquals((long)    x, (long)    mh_jc.invokeExact(x));  // char -> long
269        assertEquals((float)   x, (float)   mh_fc.invokeExact(x));  // char -> float
270        assertEquals((double)  x, (double)  mh_dc.invokeExact(x));  // char -> double
271        if (!DO_CASTS)  return;
272        boolean z = ((x & 1) != 0);
273        assertEquals((boolean) z, (boolean) mh_zc.invokeExact(x));  // char -> boolean
274        assertEquals((byte)    x, (byte)    mh_bc.invokeExact(x));  // char -> byte
275        assertEquals((short)   x, (short)   mh_sc.invokeExact(x));  // char -> short
276    }
277    private static void char2prim_invalid(char x) throws Throwable {
278        if (DO_CASTS)  return;
279        try { boolean y = (boolean) mh_zc.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // char -> boolean
280        try { byte    y = (byte)    mh_bc.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // char -> byte
281        try { short   y = (short)   mh_sc.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // char -> short
282    }
283
284    private static MethodHandle mh_s(Class ret) { return mh(ret, short.class); }
285
286    private static final MethodHandle mh_zs = mh_s(boolean.class);
287    private static final MethodHandle mh_bs = mh_s(byte.class   );
288    private static final MethodHandle mh_cs = mh_s(char.class   );
289    private static final MethodHandle mh_ss = mh_s(short.class  );
290    private static final MethodHandle mh_is = mh_s(int.class    );
291    private static final MethodHandle mh_js = mh_s(long.class   );
292    private static final MethodHandle mh_fs = mh_s(float.class  );
293    private static final MethodHandle mh_ds = mh_s(double.class );
294
295    private static void short2prim(short x) throws Throwable {
296        assertEquals((short)   x, (short)   mh_ss.invokeExact(x));  // short -> short
297        assertEquals((int)     x, (int)     mh_is.invokeExact(x));  // short -> int
298        assertEquals((long)    x, (long)    mh_js.invokeExact(x));  // short -> long
299        assertEquals((float)   x, (float)   mh_fs.invokeExact(x));  // short -> float
300        assertEquals((double)  x, (double)  mh_ds.invokeExact(x));  // short -> double
301        if (!DO_CASTS)  return;
302        boolean z = ((x & 1) != 0);
303        assertEquals((boolean) z, (boolean) mh_zs.invokeExact(x));  // short -> boolean
304        assertEquals((byte)    x, (byte)    mh_bs.invokeExact(x));  // short -> byte
305        assertEquals((char)    x, (char)    mh_cs.invokeExact(x));  // short -> char
306    }
307    private static void short2prim_invalid(short x) throws Throwable {
308        if (DO_CASTS)  return;
309        try { boolean y = (boolean) mh_zs.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // short -> boolean
310        try { byte    y = (byte)    mh_bs.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // short -> byte
311        try { char    y = (char)    mh_cs.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // short -> char
312    }
313
314    private static MethodHandle mh_i(Class ret) { return mh(ret, int.class); }
315
316    private static final MethodHandle mh_zi = mh_i(boolean.class);
317    private static final MethodHandle mh_bi = mh_i(byte.class   );
318    private static final MethodHandle mh_ci = mh_i(char.class   );
319    private static final MethodHandle mh_si = mh_i(short.class  );
320    private static final MethodHandle mh_ii = mh_i(int.class    );
321    private static final MethodHandle mh_ji = mh_i(long.class   );
322    private static final MethodHandle mh_fi = mh_i(float.class  );
323    private static final MethodHandle mh_di = mh_i(double.class );
324
325    private static void int2prim(int x) throws Throwable {
326        assertEquals((int)     x, (int)     mh_ii.invokeExact(x));  // int -> int
327        assertEquals((long)    x, (long)    mh_ji.invokeExact(x));  // int -> long
328        assertEquals((float)   x, (float)   mh_fi.invokeExact(x));  // int -> float
329        assertEquals((double)  x, (double)  mh_di.invokeExact(x));  // int -> double
330        if (!DO_CASTS)  return;
331        boolean z = ((x & 1) != 0);
332        assertEquals((boolean) z, (boolean) mh_zi.invokeExact(x));  // int -> boolean
333        assertEquals((byte)    x, (byte)    mh_bi.invokeExact(x));  // int -> byte
334        assertEquals((char)    x, (char)    mh_ci.invokeExact(x));  // int -> char
335        assertEquals((short)   x, (short)   mh_si.invokeExact(x));  // int -> short
336    }
337    private static void int2prim_invalid(int x) throws Throwable {
338        if (DO_CASTS)  return;
339        try { boolean y = (boolean) mh_zi.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // int -> boolean
340        try { byte    y = (byte)    mh_bi.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // int -> byte
341        try { char    y = (char)    mh_ci.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // int -> char
342        try { short   y = (short)   mh_si.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // int -> short
343    }
344
345    private static MethodHandle mh_j(Class ret) { return mh(ret, long.class); }
346
347    private static final MethodHandle mh_zj = mh_j(boolean.class);
348    private static final MethodHandle mh_bj = mh_j(byte.class   );
349    private static final MethodHandle mh_cj = mh_j(char.class   );
350    private static final MethodHandle mh_sj = mh_j(short.class  );
351    private static final MethodHandle mh_ij = mh_j(int.class    );
352    private static final MethodHandle mh_jj = mh_j(long.class   );
353    private static final MethodHandle mh_fj = mh_j(float.class  );
354    private static final MethodHandle mh_dj = mh_j(double.class );
355
356    private static void long2prim(long x) throws Throwable {
357        assertEquals((long)   x, (long)    mh_jj.invokeExact(x));  // long -> long
358        assertEquals((float)  x, (float)   mh_fj.invokeExact(x));  // long -> float
359        assertEquals((double) x, (double)  mh_dj.invokeExact(x));  // long -> double
360        if (!DO_CASTS)  return;
361        boolean z = ((x & 1) != 0);
362        assertEquals((boolean)z, (boolean) mh_zj.invokeExact(x));  // long -> boolean
363        assertEquals((byte)   x, (byte)    mh_bj.invokeExact(x));  // long -> byte
364        assertEquals((char)   x, (char)    mh_cj.invokeExact(x));  // long -> char
365        assertEquals((short)  x, (short)   mh_sj.invokeExact(x));  // long -> short
366        assertEquals((int)    x, (int)     mh_ij.invokeExact(x));  // long -> int
367    }
368    private static void long2prim_invalid(long x) throws Throwable {
369        if (DO_CASTS)  return;
370        try { boolean y = (boolean) mh_zj.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // long -> boolean
371        try { byte    y = (byte)    mh_bj.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // long -> byte
372        try { char    y = (char)    mh_cj.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // long -> char
373        try { short   y = (short)   mh_sj.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // long -> short
374        try { int     y = (int)     mh_ij.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // long -> int
375    }
376
377    private static MethodHandle mh_f(Class ret) { return mh(ret, float.class); }
378
379    private static final MethodHandle mh_zf = mh_f(boolean.class);
380    private static final MethodHandle mh_bf = mh_f(byte.class   );
381    private static final MethodHandle mh_cf = mh_f(char.class   );
382    private static final MethodHandle mh_sf = mh_f(short.class  );
383    private static final MethodHandle mh_if = mh_f(int.class    );
384    private static final MethodHandle mh_jf = mh_f(long.class   );
385    private static final MethodHandle mh_ff = mh_f(float.class  );
386    private static final MethodHandle mh_df = mh_f(double.class );
387
388    private static void float2prim(float x) throws Throwable {
389        assertEquals((float)   x, (float)   mh_ff.invokeExact(x));  // float -> float
390        assertEquals((double)  x, (double)  mh_df.invokeExact(x));  // float -> double
391        if (!DO_CASTS)  return;
392        boolean z = (((byte) x & 1) != 0);
393        assertEquals((boolean) z, (boolean) mh_zf.invokeExact(x));  // float -> boolean
394        assertEquals((byte)    x, (byte)    mh_bf.invokeExact(x));  // float -> byte
395        assertEquals((char)    x, (char)    mh_cf.invokeExact(x));  // float -> char
396        assertEquals((short)   x, (short)   mh_sf.invokeExact(x));  // float -> short
397        assertEquals((int)     x, (int)     mh_if.invokeExact(x));  // float -> int
398        assertEquals((long)    x, (long)    mh_jf.invokeExact(x));  // float -> long
399    }
400    private static void float2prim_invalid(float x) throws Throwable {
401        if (DO_CASTS)  return;
402        try { boolean y = (boolean) mh_zf.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> boolean
403        try { byte    y = (byte)    mh_bf.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> byte
404        try { char    y = (char)    mh_cf.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> char
405        try { short   y = (short)   mh_sf.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> short
406        try { int     y = (int)     mh_if.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> int
407        try { long    y = (long)    mh_jf.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // float -> long
408    }
409
410    private static MethodHandle mh_d(Class ret) { return mh(ret, double.class); }
411
412    private static final MethodHandle mh_zd = mh_d(boolean.class);
413    private static final MethodHandle mh_bd = mh_d(byte.class   );
414    private static final MethodHandle mh_cd = mh_d(char.class   );
415    private static final MethodHandle mh_sd = mh_d(short.class  );
416    private static final MethodHandle mh_id = mh_d(int.class    );
417    private static final MethodHandle mh_jd = mh_d(long.class   );
418    private static final MethodHandle mh_fd = mh_d(float.class  );
419    private static final MethodHandle mh_dd = mh_d(double.class );
420
421    private static void double2prim(double x) throws Throwable {
422        assertEquals((double) x, (double)  mh_dd.invokeExact(x));  // double -> double
423        if (!DO_CASTS)  return;
424        boolean z = (((byte) x & 1) != 0);
425        assertEquals((boolean) z, (boolean) mh_zd.invokeExact(x));  // double -> boolean
426        assertEquals((byte)    x, (byte)    mh_bd.invokeExact(x));  // double -> byte
427        assertEquals((char)    x, (char)    mh_cd.invokeExact(x));  // double -> char
428        assertEquals((short)   x, (short)   mh_sd.invokeExact(x));  // double -> short
429        assertEquals((int)     x, (int)     mh_id.invokeExact(x));  // double -> int
430        assertEquals((long)    x, (long)    mh_jd.invokeExact(x));  // double -> long
431        assertEquals((float)   x, (float)   mh_fd.invokeExact(x));  // double -> float
432    }
433    private static void double2prim_invalid(double x) throws Throwable {
434        if (DO_CASTS)  return;
435        try { boolean y = (boolean) mh_zd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> boolean
436        try { byte    y = (byte)    mh_bd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> byte
437        try { char    y = (char)    mh_cd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> char
438        try { short   y = (short)   mh_sd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> short
439        try { int     y = (int)     mh_id.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> int
440        try { long    y = (long)    mh_jd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> long
441        try { float   y = (float)   mh_fd.invokeExact(x); fail(); } catch (ClassCastException expected) {}  // double -> float
442    }
443
444    private static final MethodHandle mh_zv = mh(boolean.class);
445    private static final MethodHandle mh_bv = mh(byte.class   );
446    private static final MethodHandle mh_cv = mh(char.class   );
447    private static final MethodHandle mh_sv = mh(short.class  );
448    private static final MethodHandle mh_iv = mh(int.class    );
449    private static final MethodHandle mh_jv = mh(long.class   );
450    private static final MethodHandle mh_fv = mh(float.class  );
451    private static final MethodHandle mh_dv = mh(double.class );
452
453    private static void void2prim(int i) throws Throwable {
454        assertEquals(        false, (boolean) mh_zv.invokeExact());  // void -> boolean
455        assertEquals((byte)  0,     (byte)    mh_bv.invokeExact());  // void -> byte
456        assertEquals((char)  0,     (char)    mh_cv.invokeExact());  // void -> char
457        assertEquals((short) 0,     (short)   mh_sv.invokeExact());  // void -> short
458        assertEquals(        0,     (int)     mh_iv.invokeExact());  // void -> int
459        assertEquals(        0L,    (long)    mh_jv.invokeExact());  // void -> long
460        assertEquals(        0.0f,  (float)   mh_fv.invokeExact());  // void -> float
461        assertEquals(        0.0d,  (double)  mh_dv.invokeExact());  // void -> double
462    }
463
464    private static void void2prim_invalid(double x) throws Throwable {
465        // no cases
466    }
467
468    private static MethodHandle mh_v(Class arg) { return mh(void.class, arg); }
469
470    private static final MethodHandle mh_vz = mh_v(boolean.class);
471    private static final MethodHandle mh_vb = mh_v(byte.class   );
472    private static final MethodHandle mh_vc = mh_v(char.class   );
473    private static final MethodHandle mh_vs = mh_v(short.class  );
474    private static final MethodHandle mh_vi = mh_v(int.class    );
475    private static final MethodHandle mh_vj = mh_v(long.class   );
476    private static final MethodHandle mh_vf = mh_v(float.class  );
477    private static final MethodHandle mh_vd = mh_v(double.class );
478
479    private static void prim2void(int x) throws Throwable {
480        boolean z = ((x & 1) != 0);
481        mh_vz.invokeExact(         z);  // boolean -> void
482        mh_vb.invokeExact((byte)   x);  // byte    -> void
483        mh_vc.invokeExact((char)   x);  // char    -> void
484        mh_vs.invokeExact((short)  x);  // short   -> void
485        mh_vi.invokeExact((int)    x);  // int     -> void
486        mh_vj.invokeExact((long)   x);  // long    -> void
487        mh_vf.invokeExact((float)  x);  // float   -> void
488        mh_vd.invokeExact((double) x);  // double  -> void
489    }
490
491    private static void prim2void_invalid(int x) throws Throwable {
492        // no cases
493    }
494
495    private static boolean identity(boolean v) { return v; }
496    private static byte    identity(byte    v) { return v; }
497    private static char    identity(char    v) { return v; }
498    private static short   identity(short   v) { return v; }
499    private static int     identity(int     v) { return v; }
500    private static long    identity(long    v) { return v; }
501    private static float   identity(float   v) { return v; }
502    private static double  identity(double  v) { return v; }
503    private static void    identity() {}
504}
505