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