OpenJDK / jdk / jdk
changeset 48921:576e024f10b6
8198418: Invoke LambdaMetafactory::metafactory exactly from the BootstrapMethodInvoker
Reviewed-by: briangoetz, forax, vlivanov
author | redestad |
---|---|
date | Tue, 20 Feb 2018 17:49:15 +0100 |
parents | 916690b5edc9 |
children | 906025796009 |
files | src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java |
diffstat | 2 files changed, 48 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- 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
--- 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},