Skip to content

Commit

Permalink
Enable early lookup of Lambda and LambdaForm classes in the SCC
Browse files Browse the repository at this point in the history
This patch adds:
- a unique ID to the generated Lambda and LambdaForm class names
- MethodHandleNatives functions for checking if a Lambda or LambdaForm
class is in the SCC based on the unique ID
- early SCC-lookup for both Lambda and LambdaForm classes

Signed-off-by: Nathan Henderson nathan.henderson@ibm.com
  • Loading branch information
ThanHenderson committed Jul 31, 2024
1 parent ba28da9 commit cc22819
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/

package java.lang.invoke;

import jdk.internal.org.objectweb.asm.*;
Expand Down Expand Up @@ -163,7 +169,29 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
implMethodName = implInfo.getName();
implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
constructorType = invokedType.changeReturnType(Void.TYPE);
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
String rawUniqueID = targetClass.getName()
+ invokedType.toString()
+ samMethodName
+ samMethodType.toString()
+ instantiatedMethodType.toString()
+ implMethodClassName
+ implMethodName
+ implMethodDesc;
StringBuilder encodedUniqueID = new StringBuilder();
String parentheses = "(){}[]<>";
for (int i = 0; i < rawUniqueID.length(); i++) {
char currentChar = rawUniqueID.charAt(i);
if (Character.isLetterOrDigit(currentChar)) {
encodedUniqueID.append(currentChar);
} else {
if (parentheses.indexOf(currentChar) != -1) {
encodedUniqueID.append("__");
} else {
encodedUniqueID.append('_');
}
}
}
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + encodedUniqueID.toString();
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
int parameterCount = invokedType.parameterCount();
if (parameterCount > 0) {
Expand Down Expand Up @@ -252,6 +280,10 @@ public Constructor<?>[] run() {
* is not found
*/
private Class<?> spinInnerClass() throws LambdaConversionException {
Class<?> innerClass = MethodHandleNatives.findLambdaInSCC(lambdaClassName, targetClass);
if (innerClass != null) {
return innerClass;
}
String[] interfaces;
String samIntf = samBase.getName().replace('.', '/');
boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/


package java.lang.invoke;

import jdk.internal.org.objectweb.asm.ClassWriter;
Expand Down Expand Up @@ -111,7 +118,22 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
if (DUMP_CLASS_FILES) {
className = makeDumpableClassName(className);
}
this.className = className;
String rawUniqueID = className + invokerName + invokerType.toString() + lambdaForm.toString();
StringBuilder encodedUniqueID = new StringBuilder();
String parentheses = "(){}[]<>";
for (int i = 0; i < rawUniqueID.length(); i++) {
char currentChar = rawUniqueID.charAt(i);
if (Character.isLetterOrDigit(currentChar)) {
encodedUniqueID.append(currentChar);
} else {
if (parentheses.indexOf(currentChar) != -1) {
encodedUniqueID.append("__");
} else {
encodedUniqueID.append('_');
}
}
}
this.className = className + "$" + encodedUniqueID.toString();
this.lambdaForm = lambdaForm;
this.invokerName = invokerName;
this.invokerType = invokerType;
Expand Down Expand Up @@ -690,6 +712,10 @@ static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType
if (pregenerated != null) return pregenerated; // pre-generated bytecode

InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
Class<?> customized = MethodHandleNatives.findLambdaFormInSCC(CLASS_PREFIX + g.className, HOST_CLASS);
if (customized != null) {
return resolveInvokerMember(customized, g.invokerName, g.invokerType);
}
return g.loadMethod(g.generateCustomizedCodeBytes());
}

Expand Down Expand Up @@ -1766,6 +1792,10 @@ static MemberName generateLambdaFormInterpreterEntryPoint(MethodType mt) {
MethodType type = mt; // includes leading argument
type = type.changeParameterType(0, MethodHandle.class);
InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type);
Class<?> customized = MethodHandleNatives.findLambdaFormInSCC(CLASS_PREFIX + g.className, HOST_CLASS);
if (customized != null) {
return resolveInvokerMember(customized, g.invokerName, g.invokerType);
}
return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes());
}

Expand Down Expand Up @@ -1825,6 +1855,10 @@ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) {
MethodType invokerType = NamedFunction.INVOKER_METHOD_TYPE;
String invokerName = "invoke_" + shortenSignature(basicTypeSignature(typeForm.erasedType()));
InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType);
Class<?> customized = MethodHandleNatives.findLambdaFormInSCC(CLASS_PREFIX + g.className, HOST_CLASS);
if (customized != null) {
return resolveInvokerMember(customized, g.invokerName, g.invokerType);
}
return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/

package java.lang.invoke;

import jdk.internal.ref.CleanerFactory;
Expand All @@ -49,6 +55,8 @@ private MethodHandleNatives() { } // static only

static native void init(MemberName self, Object ref);
static native void expand(MemberName self);
static native Class<?> findLambdaFormInSCC(String classname, Class<?> hostClass);
static native Class<?> findLambdaInSCC(String classname, Class<?> hostClass);
static native MemberName resolve(MemberName self, Class<?> caller,
boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
static native int getMembers(Class<?> defc, String matchName, String matchSig,
Expand Down

0 comments on commit cc22819

Please sign in to comment.