Skip to content
Permalink
Browse files
8260605: Various java.lang.invoke cleanups
Reviewed-by: mchung
  • Loading branch information
cl4es committed Mar 18, 2021
1 parent 9cd21b6 commit 63eae8fac2006e208dd5781976e7c6f8f446d4cd
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 246 deletions.
@@ -84,10 +84,13 @@ static <T> T invoke(Class<T> resultType,
// By providing static type information or even invoking
// exactly, we avoid emitting code to perform runtime
// checking.
info = maybeReBox(info);
if (info == null) {
// VM is allowed to pass up a null meaning no BSM args
result = invoke(bootstrapMethod, caller, name, type);
if (type instanceof Class<?> c) {
result = bootstrapMethod.invoke(caller, name, c);
} else {
result = bootstrapMethod.invoke(caller, name, (MethodType)type);
}
}
else if (!info.getClass().isArray()) {
// VM is allowed to pass up a single BSM arg directly
@@ -99,7 +102,12 @@ else if (!info.getClass().isArray()) {
.invokeExact(caller, name, (MethodType)type,
(String)info, new Object[0]);
} else {
result = invoke(bootstrapMethod, caller, name, type, info);
info = maybeReBox(info);
if (type instanceof Class<?> c) {
result = bootstrapMethod.invoke(caller, name, c, info);
} else {
result = bootstrapMethod.invoke(caller, name, (MethodType)type, info);
}
}
}
else if (info.getClass() == int[].class) {
@@ -119,7 +127,6 @@ else if (info.getClass() == int[].class) {
else {
// VM is allowed to pass up a full array of resolved BSM args
Object[] argv = (Object[]) info;
maybeReBoxElements(argv);

MethodType bsmType = bootstrapMethod.type();
if (isLambdaMetafactoryIndyBSM(bsmType) && argv.length == 3) {
@@ -133,40 +140,36 @@ else if (info.getClass() == int[].class) {
} else if (isStringConcatFactoryBSM(bsmType) && argv.length >= 1) {
String recipe = (String)argv[0];
Object[] shiftedArgs = Arrays.copyOfRange(argv, 1, argv.length);
maybeReBoxElements(shiftedArgs);
result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, recipe, shiftedArgs);
} else if (isLambdaMetafactoryAltMetafactoryBSM(bsmType)) {
maybeReBoxElements(argv);
result = (CallSite)bootstrapMethod.invokeExact(caller, name, (MethodType)type, argv);
} else {
switch (argv.length) {
case 0:
result = invoke(bootstrapMethod, caller, name, type);
break;
case 1:
result = invoke(bootstrapMethod, caller, name, type,
argv[0]);
break;
case 2:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1]);
break;
case 3:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2]);
break;
case 4:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3]);
break;
case 5:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3], argv[4]);
break;
case 6:
result = invoke(bootstrapMethod, caller, name, type,
argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
break;
default:
result = invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
maybeReBoxElements(argv);
if (type instanceof Class<?> c) {
result = switch (argv.length) {
case 0 -> bootstrapMethod.invoke(caller, name, c);
case 1 -> bootstrapMethod.invoke(caller, name, c, argv[0]);
case 2 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1]);
case 3 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2]);
case 4 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3]);
case 5 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6 -> bootstrapMethod.invoke(caller, name, c, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
default -> invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
};
} else {
MethodType mt = (MethodType) type;
result = switch (argv.length) {
case 0 -> bootstrapMethod.invoke(caller, name, mt);
case 1 -> bootstrapMethod.invoke(caller, name, mt, argv[0]);
case 2 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1]);
case 3 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2]);
case 4 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3]);
case 5 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6 -> bootstrapMethod.invoke(caller, name, mt, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
default -> invokeWithManyArguments(bootstrapMethod, caller, name, type, argv);
};
}
}
}
@@ -218,76 +221,6 @@ static <T> T widenAndCast(Object result, Class<T> resultType) throws Throwable {
return wrapperType.cast(result);
}

// If we don't provide static type information for type, we'll generate runtime
// checks. Let's try not to...

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1,
Object arg2) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller, String name,
Object type, Object arg0, Object arg1,
Object arg2, Object arg3) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0, Object arg1,
Object arg2, Object arg3, Object arg4) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3, arg4);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3, arg4);
}
}

private static Object invoke(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object arg0, Object arg1,
Object arg2, Object arg3, Object arg4, Object arg5) throws Throwable {
if (type instanceof Class) {
return bootstrapMethod.invoke(caller, name, (Class<?>)type, arg0, arg1, arg2, arg3, arg4, arg5);
} else {
return bootstrapMethod.invoke(caller, name, (MethodType)type, arg0, arg1, arg2, arg3, arg4, arg5);
}
}

private static Object invokeWithManyArguments(MethodHandle bootstrapMethod, Lookup caller,
String name, Object type, Object[] argv) throws Throwable {
final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)

0 comments on commit 63eae8f

Please sign in to comment.