# HG changeset patch # User redestad # Date 1519145355 -3600 # Node ID 576e024f10b6e7d54046c73844119d5191697a9d # Parent 916690b5edc951f4b4d880473947704eabf725ab 8198418: Invoke LambdaMetafactory::metafactory exactly from the BootstrapMethodInvoker Reviewed-by: briangoetz, forax, vlivanov diff -r 916690b5edc9 -r 576e024f10b6 src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java --- a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java Tue Feb 20 11:45:16 2018 -0500 +++ b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java Tue Feb 20 17:49:15 2018 +0100 @@ -116,8 +116,24 @@ argv[0], argv[1]); break; case 3: - result = bootstrapMethod.invoke(caller, name, type, - argv[0], argv[1], argv[2]); + // Special case the LambdaMetafactory::metafactory BSM + // + // By invoking exactly, we can avoid generating a number of + // classes on first (and subsequent) lambda initialization, + // most of which won't be shared with other invoke uses. + MethodType bsmType = bootstrapMethod.type(); + if (isLambdaMetafactoryIndyBSM(bsmType)) { + result = (CallSite)bootstrapMethod + .invokeExact(caller, name, (MethodType)type, (MethodType)argv[0], + (MethodHandle)argv[1], (MethodType)argv[2]); + } else if (isLambdaMetafactoryCondyBSM(bsmType)) { + result = bootstrapMethod + .invokeExact(caller, name, (Class)type, (MethodType)argv[0], + (MethodHandle)argv[1], (MethodType)argv[2]); + } else { + result = bootstrapMethod.invoke(caller, name, type, + argv[0], argv[1], argv[2]); + } break; case 4: result = bootstrapMethod.invoke(caller, name, type, @@ -175,6 +191,30 @@ } } + private static final MethodType LMF_INDY_MT = MethodType.methodType(CallSite.class, + Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + + private static final MethodType LMF_CONDY_MT = MethodType.methodType(Object.class, + Lookup.class, String.class, Class.class, MethodType.class, MethodHandle.class, MethodType.class); + + /** + * @return true iff the BSM method type exactly matches + * {@see java.lang.invoke.LambdaMetafactory#metafactory( + * MethodHandles.Lookup,String,Class,MethodType,MethodHandle,MethodType)} + */ + private static boolean isLambdaMetafactoryCondyBSM(MethodType bsmType) { + return bsmType == LMF_CONDY_MT; + } + + /** + * @return true iff the BSM method type exactly matches + * {@see java.lang.invoke.LambdaMetafactory#metafactory( + * MethodHandles.Lookup,String,MethodType,MethodType,MethodHandle,MethodType)} + */ + private static boolean isLambdaMetafactoryIndyBSM(MethodType bsmType) { + return bsmType == LMF_INDY_MT; + } + /** The JVM produces java.lang.Integer values to box * CONSTANT_Integer boxes but does not intern them. * Let's intern them. This is slightly wrong for diff -r 916690b5edc9 -r 576e024f10b6 src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java --- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Tue Feb 20 11:45:16 2018 -0500 +++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Tue Feb 20 17:49:15 2018 +0100 @@ -242,6 +242,12 @@ private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0]; + // LambdaMetafactory bootstrap methods are startup sensitive, and may be + // special cased in java.lang.invokeBootstrapMethodInvoker to ensure + // methods are invoked with exact type information to avoid generating + // code for runtime checks. Take care any changes or additions here are + // reflected there as appropriate. + /** * Facilitates the creation of simple "function objects" that implement one * or more interfaces by delegation to a provided {@link MethodHandle},