8327499: MethodHandleStatics.traceLambdaForm includes methods that cannot be generated

Reviewed-by: redestad, iklam
This commit is contained in:
Chen Liang 2024-05-13 09:11:49 +00:00 committed by Claes Redestad
parent 5a8df4106a
commit adaa509b6e
5 changed files with 140 additions and 34 deletions

View file

@ -28,7 +28,6 @@ package java.lang.invoke;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
import sun.invoke.util.Wrapper;
import sun.util.logging.PlatformLogger;
import java.util.ArrayList;
import java.util.HashSet;
@ -73,6 +72,7 @@ class GenerateJLIClassesHelper {
private final TreeSet<String> speciesTypes = new TreeSet<>();
private final TreeSet<String> invokerTypes = new TreeSet<>();
private final TreeSet<String> linkerTypes = new TreeSet<>();
private final TreeSet<String> callSiteTypes = new TreeSet<>();
private final Map<String, Set<String>> dmhMethods = new TreeMap<>();
@ -87,6 +87,12 @@ class GenerateJLIClassesHelper {
return this;
}
HolderClassBuilder addLinkerType(String methodType) {
validateMethodType(methodType);
linkerTypes.add(methodType);
return this;
}
HolderClassBuilder addCallSiteType(String csType) {
validateMethodType(csType);
callSiteTypes.add(csType);
@ -130,19 +136,33 @@ class GenerateJLIClassesHelper {
}
}
// The invoker type to ask for is retrieved by removing the first
// The linker type to ask for is retrieved by removing the first
// and the last argument, which needs to be of Object.class
MethodType[] linkerMethodTypes = new MethodType[linkerTypes.size()];
index = 0;
for (String linkerType : linkerTypes) {
MethodType mt = asMethodType(linkerType);
final int lastParam = mt.parameterCount() - 1;
if (!checkLinkerTypeParams(mt)) {
throw new RuntimeException(
"Linker type parameter must start and end with Object: " + linkerType);
}
mt = mt.dropParameterTypes(lastParam, lastParam + 1);
linkerMethodTypes[index] = mt.dropParameterTypes(0, 1);
index++;
}
// The invoker type to ask for is retrieved by removing the first
// argument, which needs to be of Object.class
MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()];
index = 0;
for (String invokerType : invokerTypes) {
MethodType mt = asMethodType(invokerType);
final int lastParam = mt.parameterCount() - 1;
if (!checkInvokerTypeParams(mt)) {
throw new RuntimeException(
"Invoker type parameter must start and end with Object: " + invokerType);
"Invoker type parameter must start with 2 Objects: " + invokerType);
}
mt = mt.dropParameterTypes(lastParam, lastParam + 1);
invokerMethodTypes[index] = mt.dropParameterTypes(0, 1);
invokerMethodTypes[index] = mt.dropParameterTypes(0, 2);
index++;
}
@ -171,7 +191,7 @@ class GenerateJLIClassesHelper {
DELEGATING_HOLDER, directMethodTypes));
result.put(INVOKERS_HOLDER,
generateInvokersHolderClassBytes(INVOKERS_HOLDER,
invokerMethodTypes, callSiteMethodTypes));
linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes));
result.put(BASIC_FORMS_HOLDER,
generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
@ -207,6 +227,12 @@ class GenerateJLIClassesHelper {
}
public static boolean checkInvokerTypeParams(MethodType mt) {
return (mt.parameterCount() >= 2 &&
mt.parameterType(0) == Object.class &&
mt.parameterType(1) == Object.class);
}
public static boolean checkLinkerTypeParams(MethodType mt) {
final int lastParam = mt.parameterCount() - 1;
return (mt.parameterCount() >= 2 &&
mt.parameterType(0) == Object.class &&
@ -320,15 +346,11 @@ class GenerateJLIClassesHelper {
if ("linkToTargetMethod".equals(parts[2]) ||
"linkToCallSite".equals(parts[2])) {
builder.addCallSiteType(methodType);
} else if (parts[2].endsWith("nvoker")) {
// MH.exactInvoker exactInvoker MH.invoker invoker
builder.addInvokerType(methodType);
} else {
MethodType mt = HolderClassBuilder.asMethodType(methodType);
// Work around JDK-8327499
if (HolderClassBuilder.checkInvokerTypeParams(mt)) {
builder.addInvokerType(methodType);
} else {
PlatformLogger.getLogger("java.lang.invoke")
.warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]);
}
builder.addLinkerType(methodType);
}
} else if (parts[1].contains("DirectMethodHandle")) {
String dmh = parts[2];
@ -465,27 +487,27 @@ class GenerateJLIClassesHelper {
/**
* Returns a {@code byte[]} representation of a class implementing
* the invoker forms for the set of supplied {@code invokerMethodTypes}
* and {@code callSiteMethodTypes}.
* the invoker forms for the set of supplied {@code linkerMethodTypes}
* {@code invokerMethodTypes}, and {@code callSiteMethodTypes}.
*/
static byte[] generateInvokersHolderClassBytes(String className,
MethodType[] invokerMethodTypes, MethodType[] callSiteMethodTypes) {
MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes,
MethodType[] callSiteMethodTypes) {
HashSet<MethodType> dedupSet = new HashSet<>();
ArrayList<LambdaForm> forms = new ArrayList<>();
ArrayList<String> names = new ArrayList<>();
int[] types = {
MethodTypeForm.LF_EX_LINKER,
int[] invokerTypes = {
MethodTypeForm.LF_EX_INVOKER,
MethodTypeForm.LF_GEN_LINKER,
MethodTypeForm.LF_GEN_INVOKER
MethodTypeForm.LF_GEN_INVOKER,
};
for (int i = 0; i < invokerMethodTypes.length; i++) {
for (MethodType methodType : invokerMethodTypes) {
// generate methods representing invokers of the specified type
if (dedupSet.add(invokerMethodTypes[i])) {
for (int type : types) {
LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i],
if (dedupSet.add(methodType)) {
for (int type : invokerTypes) {
LambdaForm invokerForm = Invokers.invokeHandleForm(methodType,
/*customized*/false, type);
forms.add(invokerForm);
names.add(invokerForm.kind.defaultLambdaName);
@ -493,6 +515,24 @@ class GenerateJLIClassesHelper {
}
}
int[] linkerTypes = {
MethodTypeForm.LF_EX_LINKER,
MethodTypeForm.LF_GEN_LINKER,
};
dedupSet = new HashSet<>();
for (MethodType methodType : linkerMethodTypes) {
// generate methods representing linkers of the specified type
if (dedupSet.add(methodType)) {
for (int type : linkerTypes) {
LambdaForm linkerForm = Invokers.invokeHandleForm(methodType,
/*customized*/false, type);
forms.add(linkerForm);
names.add(linkerForm.kind.defaultLambdaName);
}
}
}
dedupSet = new HashSet<>();
for (int i = 0; i < callSiteMethodTypes.length; i++) {
// generate methods representing invokers of the specified type