< prev index next > src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
Print this page
*/
package java.lang.invoke;
import sun.invoke.util.Wrapper;
+ import sun.util.logging.PlatformLogger;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.SourceFileAttribute;
import java.lang.constant.ClassDesc;
import java.util.ArrayList;
static class HolderClassBuilder {
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<>();
HolderClassBuilder addSpeciesType(String type) {
speciesTypes.add(expandSignature(type));
validateMethodType(methodType);
invokerTypes.add(methodType);
return this;
}
- HolderClassBuilder addLinkerType(String methodType) {
- validateMethodType(methodType);
- linkerTypes.add(methodType);
- return this;
- }
-
HolderClassBuilder addCallSiteType(String csType) {
validateMethodType(csType);
callSiteTypes.add(csType);
return this;
}
if (mt.parameterCount() < 1 ||
mt.parameterType(0) != Object.class) {
throw new RuntimeException(
"DMH type parameter must start with L: " + dmhType + " " + type);
}
-
// Adapt the method type of the LF to retrieve
directMethodTypes[index] = mt.dropParameterTypes(0, 1);
-
// invokeVirtual and invokeInterface must have a leading Object
// parameter, i.e., the receiver
dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
if (dmhTypes[index] == LF_INVINTERFACE || dmhTypes[index] == LF_INVVIRTUAL) {
if (mt.parameterCount() < 2 ||
}
index++;
}
}
- // 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);
if (!checkInvokerTypeParams(mt)) {
throw new RuntimeException(
! "Invoker type parameter must start with 2 Objects: " + invokerType);
}
! invokerMethodTypes[index] = mt.dropParameterTypes(0, 2);
index++;
}
// The callSite type to ask for is retrieved by removing the last
// argument, which needs to be of Object.class
}
index++;
}
}
// The invoker type to ask for is retrieved by removing the first
! // and the last 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);
}
! mt = mt.dropParameterTypes(lastParam, lastParam + 1);
+ invokerMethodTypes[index] = mt.dropParameterTypes(0, 1);
index++;
}
// The callSite type to ask for is retrieved by removing the last
// argument, which needs to be of Object.class
"CallSite type parameter must end with Object: " + callSiteType);
}
callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
index++;
}
-
Map<String, byte[]> result = new TreeMap<>();
result.put(DIRECT_HOLDER,
generateDirectMethodHandleHolderClassBytes(
DIRECT_HOLDER, directMethodTypes, dmhTypes));
result.put(DELEGATING_HOLDER,
generateDelegatingMethodHandleHolderClassBytes(
DELEGATING_HOLDER, directMethodTypes));
result.put(INVOKERS_HOLDER,
generateInvokersHolderClassBytes(INVOKERS_HOLDER,
! linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes));
result.put(BASIC_FORMS_HOLDER,
generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
speciesTypes.forEach(types -> {
Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
result.put(entry.getKey(), entry.getValue());
});
-
// clear builder
speciesTypes.clear();
invokerTypes.clear();
callSiteTypes.clear();
dmhMethods.clear();
-
return result;
}
public static MethodType asMethodType(String basicSignatureString) {
String[] parts = basicSignatureString.split("_");
"CallSite type parameter must end with Object: " + callSiteType);
}
callSiteMethodTypes[index] = mt.dropParameterTypes(lastParam, lastParam + 1);
index++;
}
Map<String, byte[]> result = new TreeMap<>();
result.put(DIRECT_HOLDER,
generateDirectMethodHandleHolderClassBytes(
DIRECT_HOLDER, directMethodTypes, dmhTypes));
result.put(DELEGATING_HOLDER,
generateDelegatingMethodHandleHolderClassBytes(
DELEGATING_HOLDER, directMethodTypes));
result.put(INVOKERS_HOLDER,
generateInvokersHolderClassBytes(INVOKERS_HOLDER,
! invokerMethodTypes, callSiteMethodTypes));
result.put(BASIC_FORMS_HOLDER,
generateBasicFormsClassBytes(BASIC_FORMS_HOLDER));
speciesTypes.forEach(types -> {
Map.Entry<String, byte[]> entry = generateConcreteBMHClassBytes(types);
result.put(entry.getKey(), entry.getValue());
});
// clear builder
speciesTypes.clear();
invokerTypes.clear();
callSiteTypes.clear();
dmhMethods.clear();
return result;
}
public static MethodType asMethodType(String basicSignatureString) {
String[] parts = basicSignatureString.split("_");
return MethodType.methodType(rtype, ptypes);
}
}
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 &&
mt.parameterType(lastParam) == Object.class);
}
String methodType = parts[3];
if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
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 {
! builder.addLinkerType(methodType);
}
} else if (parts[1].contains("DirectMethodHandle")) {
String dmh = parts[2];
// ignore getObject etc for now (generated by default)
if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
String methodType = parts[3];
if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) {
if ("linkToTargetMethod".equals(parts[2]) ||
"linkToCallSite".equals(parts[2])) {
builder.addCallSiteType(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]);
+ }
}
} else if (parts[1].contains("DirectMethodHandle")) {
String dmh = parts[2];
// ignore getObject etc for now (generated by default)
if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
forms.toArray(new LambdaForm[0]));
}
/**
* Returns a {@code byte[]} representation of a class implementing
! * the invoker forms for the set of supplied {@code linkerMethodTypes}
! * {@code invokerMethodTypes}, and {@code callSiteMethodTypes}.
*/
static byte[] generateInvokersHolderClassBytes(String className,
! MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes,
- MethodType[] callSiteMethodTypes) {
HashSet<MethodType> dedupSet = new HashSet<>();
ArrayList<LambdaForm> forms = new ArrayList<>();
ArrayList<String> names = new ArrayList<>();
!
! int[] invokerTypes = {
MethodTypeForm.LF_EX_INVOKER,
! MethodTypeForm.LF_GEN_INVOKER,
};
! for (MethodType methodType : invokerMethodTypes) {
// generate methods representing invokers of the specified type
! if (dedupSet.add(methodType)) {
! for (int type : invokerTypes) {
! LambdaForm invokerForm = Invokers.invokeHandleForm(methodType,
/*customized*/false, type);
forms.add(invokerForm);
names.add(invokerForm.kind.defaultLambdaName);
}
}
}
- 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
if (dedupSet.add(callSiteMethodTypes[i])) {
LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
forms.toArray(new LambdaForm[0]));
}
/**
* Returns a {@code byte[]} representation of a class implementing
! * the invoker forms for the set of supplied {@code invokerMethodTypes}
! * and {@code callSiteMethodTypes}.
*/
static byte[] generateInvokersHolderClassBytes(String className,
! 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,
MethodTypeForm.LF_EX_INVOKER,
! MethodTypeForm.LF_GEN_LINKER,
+ MethodTypeForm.LF_GEN_INVOKER
};
! for (int i = 0; i < invokerMethodTypes.length; i++) {
// generate methods representing invokers of the specified type
! if (dedupSet.add(invokerMethodTypes[i])) {
! for (int type : types) {
! LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i],
/*customized*/false, type);
forms.add(invokerForm);
names.add(invokerForm.kind.defaultLambdaName);
}
}
}
dedupSet = new HashSet<>();
for (int i = 0; i < callSiteMethodTypes.length; i++) {
// generate methods representing invokers of the specified type
if (dedupSet.add(callSiteMethodTypes[i])) {
LambdaForm callSiteForm = Invokers.callSiteForm(callSiteMethodTypes[i], true);
< prev index next >