src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 9328 : 8027827: Improve performance of catchException combinator
8034120: MethodHandles.catchException doesn't handle VarargsCollector right
Reviewed-by: lagergren, psandoz, ?
rev 9329 : 8033666: Make sure @ForceInline is everywhere it needs to be in sun.misc and java.lang.invoke
Reviewed-by: ?


 236                         // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
 237                         // must include additional conversions
 238                         // src must be examined at runtime, to detect Byte, Character, etc.
 239                         MethodHandle unboxMethod = (level == 1
 240                                                     ? ValueConversions.unbox(dst)
 241                                                     : ValueConversions.unboxCast(dst));
 242                         fn = unboxMethod;
 243                     } else {
 244                         // Example: Byte->int
 245                         // Do this by reformulating the problem to Byte->byte.
 246                         Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
 247                         MethodHandle unbox = ValueConversions.unbox(srcPrim);
 248                         // Compose the two conversions.  FIXME:  should make two Names for this job
 249                         fn = unbox.asType(MethodType.methodType(dst, src));
 250                     }
 251                 } else {
 252                     // Simple reference conversion.
 253                     // Note:  Do not check for a class hierarchy relation
 254                     // between src and dst.  In all cases a 'null' argument
 255                     // will pass the cast conversion.
 256                     fn = ValueConversions.cast(dst);
 257                 }
 258             }
 259             Name conv = new Name(fn, names[INARG_BASE + i]);
 260             assert(names[nameCursor] == null);
 261             names[nameCursor++] = conv;
 262             assert(outArgs[OUTARG_BASE + i] == null);
 263             outArgs[OUTARG_BASE + i] = conv;
 264         }
 265 
 266         // Build argument array for the call.
 267         assert(nameCursor == OUT_CALL);
 268         names[OUT_CALL] = new Name(target, outArgs);
 269 
 270         if (RETURN_CONV < 0) {
 271             assert(OUT_CALL == names.length-1);
 272         } else {
 273             Class<?> needReturn = srcType.returnType();
 274             Class<?> haveReturn = dstType.returnType();
 275             MethodHandle fn;
 276             Object[] arg = { names[OUT_CALL] };
 277             if (haveReturn == void.class) {
 278                 // synthesize a zero value for the given void
 279                 Object zero = Wrapper.forBasicType(needReturn).zero();
 280                 fn = MethodHandles.constant(needReturn, zero);
 281                 arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
 282             } else {
 283                 MethodHandle identity = MethodHandles.identity(needReturn);
 284                 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
 285                 fn = makePairwiseConvert(identity, needConversion, level);
 286             }
 287             assert(names[RETURN_CONV] == null);
 288             names[RETURN_CONV] = new Name(fn, arg);
 289             assert(RETURN_CONV == names.length-1);
 290         }
 291 
 292         LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
 293         return SimpleMethodHandle.make(srcType, form);
 294     }
 295 



















 296     static MethodHandle makeReferenceIdentity(Class<?> refType) {
 297         MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
 298         Name[] names = arguments(1, lambdaType);
 299         names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
 300         LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
 301         return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
 302     }
 303 
 304     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
 305         MethodType type = target.type();
 306         int last = type.parameterCount() - 1;
 307         if (type.parameterType(last) != arrayType)
 308             target = target.asType(type.changeParameterType(last, arrayType));
 309         target = target.asFixedArity();  // make sure this attribute is turned off
 310         return new AsVarargsCollector(target, target.type(), arrayType);
 311     }
 312 
 313     static class AsVarargsCollector extends MethodHandle {
 314         private final MethodHandle target;
 315         private final Class<?> arrayType;


 471         } else {
 472             int len = java.lang.reflect.Array.getLength(av);
 473             if (len == n)  return;
 474         }
 475         // fall through to error:
 476         throw newIllegalArgumentException("array is not of length "+n);
 477     }
 478 
 479     /**
 480      * Pre-initialized NamedFunctions for bootstrapping purposes.
 481      * Factored in an inner class to delay initialization until first usage.
 482      */
 483     private static class Lazy {
 484         private static final Class<?> MHI = MethodHandleImpl.class;
 485 
 486         static final NamedFunction NF_checkSpreadArgument;
 487         static final NamedFunction NF_guardWithCatch;
 488         static final NamedFunction NF_selectAlternative;
 489         static final NamedFunction NF_throwException;
 490 


 491         static {
 492             try {
 493                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 494                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 495                         MethodHandle.class, Object[].class));
 496                 NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
 497                                                                                 MethodHandle.class));
 498                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 499 
 500                 NF_checkSpreadArgument.resolve();
 501                 NF_guardWithCatch.resolve();
 502                 NF_selectAlternative.resolve();
 503                 NF_throwException.resolve();



 504             } catch (ReflectiveOperationException ex) {
 505                 throw newInternalError(ex);
 506             }
 507         }
 508     }
 509 
 510     /** Factory method:  Collect or filter selected argument(s). */
 511     static MethodHandle makeCollectArguments(MethodHandle target,
 512                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
 513         MethodType targetType = target.type();          // (a..., c, [b...])=>r
 514         MethodType collectorType = collector.type();    // (b...)=>c
 515         int collectArgCount = collectorType.parameterCount();
 516         Class<?> collectValType = collectorType.returnType();
 517         int collectValCount = (collectValType == void.class ? 0 : 1);
 518         MethodType srcType = targetType                 // (a..., [b...])=>r
 519                 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
 520         if (!retainOriginalArgs) {                      // (a..., b...)=>r
 521             srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
 522         }
 523         // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]




 236                         // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
 237                         // must include additional conversions
 238                         // src must be examined at runtime, to detect Byte, Character, etc.
 239                         MethodHandle unboxMethod = (level == 1
 240                                                     ? ValueConversions.unbox(dst)
 241                                                     : ValueConversions.unboxCast(dst));
 242                         fn = unboxMethod;
 243                     } else {
 244                         // Example: Byte->int
 245                         // Do this by reformulating the problem to Byte->byte.
 246                         Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
 247                         MethodHandle unbox = ValueConversions.unbox(srcPrim);
 248                         // Compose the two conversions.  FIXME:  should make two Names for this job
 249                         fn = unbox.asType(MethodType.methodType(dst, src));
 250                     }
 251                 } else {
 252                     // Simple reference conversion.
 253                     // Note:  Do not check for a class hierarchy relation
 254                     // between src and dst.  In all cases a 'null' argument
 255                     // will pass the cast conversion.
 256                     fn = ValueConversions.cast(dst, Lazy.MH_castReference);
 257                 }
 258             }
 259             Name conv = new Name(fn, names[INARG_BASE + i]);
 260             assert(names[nameCursor] == null);
 261             names[nameCursor++] = conv;
 262             assert(outArgs[OUTARG_BASE + i] == null);
 263             outArgs[OUTARG_BASE + i] = conv;
 264         }
 265 
 266         // Build argument array for the call.
 267         assert(nameCursor == OUT_CALL);
 268         names[OUT_CALL] = new Name(target, outArgs);
 269 
 270         if (RETURN_CONV < 0) {
 271             assert(OUT_CALL == names.length-1);
 272         } else {
 273             Class<?> needReturn = srcType.returnType();
 274             Class<?> haveReturn = dstType.returnType();
 275             MethodHandle fn;
 276             Object[] arg = { names[OUT_CALL] };
 277             if (haveReturn == void.class) {
 278                 // synthesize a zero value for the given void
 279                 Object zero = Wrapper.forBasicType(needReturn).zero();
 280                 fn = MethodHandles.constant(needReturn, zero);
 281                 arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
 282             } else {
 283                 MethodHandle identity = MethodHandles.identity(needReturn);
 284                 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
 285                 fn = makePairwiseConvert(identity, needConversion, level);
 286             }
 287             assert(names[RETURN_CONV] == null);
 288             names[RETURN_CONV] = new Name(fn, arg);
 289             assert(RETURN_CONV == names.length-1);
 290         }
 291 
 292         LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
 293         return SimpleMethodHandle.make(srcType, form);
 294     }
 295 
 296     /**
 297      * Identity function, with reference cast.
 298      * @param t an arbitrary reference type
 299      * @param x an arbitrary reference value
 300      * @return the same value x
 301      */
 302     @ForceInline
 303     @SuppressWarnings("unchecked")
 304     static <T,U> T castReference(Class<? extends T> t, U x) {
 305         // inlined Class.cast because we can't ForceInline it
 306         if (x != null && !t.isInstance(x))
 307             throw newClassCastException(t, x);
 308         return (T) x;
 309     }
 310 
 311     private static ClassCastException newClassCastException(Class<?> t, Object obj) {
 312         return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
 313     }
 314 
 315     static MethodHandle makeReferenceIdentity(Class<?> refType) {
 316         MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
 317         Name[] names = arguments(1, lambdaType);
 318         names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
 319         LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
 320         return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
 321     }
 322 
 323     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
 324         MethodType type = target.type();
 325         int last = type.parameterCount() - 1;
 326         if (type.parameterType(last) != arrayType)
 327             target = target.asType(type.changeParameterType(last, arrayType));
 328         target = target.asFixedArity();  // make sure this attribute is turned off
 329         return new AsVarargsCollector(target, target.type(), arrayType);
 330     }
 331 
 332     static class AsVarargsCollector extends MethodHandle {
 333         private final MethodHandle target;
 334         private final Class<?> arrayType;


 490         } else {
 491             int len = java.lang.reflect.Array.getLength(av);
 492             if (len == n)  return;
 493         }
 494         // fall through to error:
 495         throw newIllegalArgumentException("array is not of length "+n);
 496     }
 497 
 498     /**
 499      * Pre-initialized NamedFunctions for bootstrapping purposes.
 500      * Factored in an inner class to delay initialization until first usage.
 501      */
 502     private static class Lazy {
 503         private static final Class<?> MHI = MethodHandleImpl.class;
 504 
 505         static final NamedFunction NF_checkSpreadArgument;
 506         static final NamedFunction NF_guardWithCatch;
 507         static final NamedFunction NF_selectAlternative;
 508         static final NamedFunction NF_throwException;
 509 
 510         static final MethodHandle MH_castReference;
 511 
 512         static {
 513             try {
 514                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 515                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 516                         MethodHandle.class, Object[].class));
 517                 NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
 518                                                                                 MethodHandle.class));
 519                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 520 
 521                 NF_checkSpreadArgument.resolve();
 522                 NF_guardWithCatch.resolve();
 523                 NF_selectAlternative.resolve();
 524                 NF_throwException.resolve();
 525 
 526                 MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class);
 527                 MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt);
 528             } catch (ReflectiveOperationException ex) {
 529                 throw newInternalError(ex);
 530             }
 531         }
 532     }
 533 
 534     /** Factory method:  Collect or filter selected argument(s). */
 535     static MethodHandle makeCollectArguments(MethodHandle target,
 536                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
 537         MethodType targetType = target.type();          // (a..., c, [b...])=>r
 538         MethodType collectorType = collector.type();    // (b...)=>c
 539         int collectArgCount = collectorType.parameterCount();
 540         Class<?> collectValType = collectorType.returnType();
 541         int collectValCount = (collectValType == void.class ? 0 : 1);
 542         MethodType srcType = targetType                 // (a..., [b...])=>r
 543                 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
 544         if (!retainOriginalArgs) {                      // (a..., b...)=>r
 545             srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
 546         }
 547         // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]


src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File