8198418: Invoke LambdaMetafactory::metafactory exactly from the BootstrapMethodInvoker

Reviewed-by: briangoetz, forax, vlivanov
This commit is contained in:
Claes Redestad 2018-02-20 17:49:15 +01:00
parent 2591c21c01
commit d4c69026bf
2 changed files with 48 additions and 2 deletions

View file

@ -116,8 +116,24 @@ final class BootstrapMethodInvoker {
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 @@ final class BootstrapMethodInvoker {
}
}
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

View file

@ -242,6 +242,12 @@ public final class LambdaMetafactory {
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},