360 static float zeroFloat() {
361 return 0;
362 }
363
364 static double zeroDouble() {
365 return 0;
366 }
367
368 private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2);
369
370 public static MethodHandle zeroConstantFunction(Wrapper wrap) {
371 WrapperCache cache = CONSTANT_FUNCTIONS[0];
372 MethodHandle mh = cache.get(wrap);
373 if (mh != null) {
374 return mh;
375 }
376 // slow path
377 MethodType type = MethodType.methodType(wrap.primitiveType());
378 switch (wrap) {
379 case VOID:
380 mh = EMPTY;
381 break;
382 case OBJECT:
383 case INT: case LONG: case FLOAT: case DOUBLE:
384 try {
385 mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
386 } catch (ReflectiveOperationException ex) {
387 mh = null;
388 }
389 break;
390 }
391 if (mh != null) {
392 return cache.put(wrap, mh);
393 }
394
395 // use zeroInt and cast the result
396 if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
397 mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
398 return cache.put(wrap, mh);
399 }
400 throw new IllegalArgumentException("cannot find zero constant for " + wrap);
401 }
402
403 private static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY;
404 static {
405 try {
406 MethodType idType = MethodType.genericMethodType(1);
407 MethodType ignoreType = idType.changeReturnType(void.class);
408 CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
409 IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
410 EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
411 } catch (NoSuchMethodException | IllegalAccessException ex) {
412 throw newInternalError("uncaught exception", ex);
413 }
414 }
415
416 public static MethodHandle ignore() {
417 return IGNORE;
418 }
419
420 /** Return a method that casts its second argument (an Object) to the given type (a Class). */
421 public static MethodHandle cast() {
422 return CAST_REFERENCE;
423 }
424
425 /// Primitive conversions.
426 // These are supported directly by the JVM, usually by a single instruction.
427 // In the case of narrowing to a subword, there may be a pair of instructions.
428 // In the case of booleans, there may be a helper routine to manage a 1-bit value.
429 // This is the full 8x8 matrix (minus the diagonal).
430
431 // narrow double to all other types:
432 static float doubleToFloat(double x) { // bytecode: d2f
433 return (float) x;
434 }
435 static long doubleToLong(double x) { // bytecode: d2l
436 return (long) x;
437 }
438 static int doubleToInt(double x) { // bytecode: d2i
439 return (int) x;
440 }
441 static short doubleToShort(double x) { // bytecodes: d2i, i2s
442 return (short) x;
|
360 static float zeroFloat() {
361 return 0;
362 }
363
364 static double zeroDouble() {
365 return 0;
366 }
367
368 private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2);
369
370 public static MethodHandle zeroConstantFunction(Wrapper wrap) {
371 WrapperCache cache = CONSTANT_FUNCTIONS[0];
372 MethodHandle mh = cache.get(wrap);
373 if (mh != null) {
374 return mh;
375 }
376 // slow path
377 MethodType type = MethodType.methodType(wrap.primitiveType());
378 switch (wrap) {
379 case VOID:
380 mh = Handles.EMPTY;
381 break;
382 case OBJECT:
383 case INT: case LONG: case FLOAT: case DOUBLE:
384 try {
385 mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
386 } catch (ReflectiveOperationException ex) {
387 mh = null;
388 }
389 break;
390 }
391 if (mh != null) {
392 return cache.put(wrap, mh);
393 }
394
395 // use zeroInt and cast the result
396 if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
397 mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
398 return cache.put(wrap, mh);
399 }
400 throw new IllegalArgumentException("cannot find zero constant for " + wrap);
401 }
402
403 private static class Handles {
404 static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY;
405 static {
406 try {
407 MethodType idType = MethodType.genericMethodType(1);
408 MethodType ignoreType = idType.changeReturnType(void.class);
409 CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
410 IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
411 EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
412 } catch (NoSuchMethodException | IllegalAccessException ex) {
413 throw newInternalError("uncaught exception", ex);
414 }
415 }
416 }
417
418 public static MethodHandle ignore() {
419 return Handles.IGNORE;
420 }
421
422 /** Return a method that casts its second argument (an Object) to the given type (a Class). */
423 public static MethodHandle cast() {
424 return Handles.CAST_REFERENCE;
425 }
426
427 /// Primitive conversions.
428 // These are supported directly by the JVM, usually by a single instruction.
429 // In the case of narrowing to a subword, there may be a pair of instructions.
430 // In the case of booleans, there may be a helper routine to manage a 1-bit value.
431 // This is the full 8x8 matrix (minus the diagonal).
432
433 // narrow double to all other types:
434 static float doubleToFloat(double x) { // bytecode: d2f
435 return (float) x;
436 }
437 static long doubleToLong(double x) { // bytecode: d2l
438 return (long) x;
439 }
440 static int doubleToInt(double x) { // bytecode: d2i
441 return (int) x;
442 }
443 static short doubleToShort(double x) { // bytecodes: d2i, i2s
444 return (short) x;
|