Skip to content

Commit cc22819

Browse files
committed
Enable early lookup of Lambda and LambdaForm classes in the SCC
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 [email protected]
1 parent ba28da9 commit cc22819

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java

+33-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
2632
package java.lang.invoke;
2733

2834
import jdk.internal.org.objectweb.asm.*;
@@ -163,7 +169,29 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
163169
implMethodName = implInfo.getName();
164170
implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
165171
constructorType = invokedType.changeReturnType(Void.TYPE);
166-
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
172+
String rawUniqueID = targetClass.getName()
173+
+ invokedType.toString()
174+
+ samMethodName
175+
+ samMethodType.toString()
176+
+ instantiatedMethodType.toString()
177+
+ implMethodClassName
178+
+ implMethodName
179+
+ implMethodDesc;
180+
StringBuilder encodedUniqueID = new StringBuilder();
181+
String parentheses = "(){}[]<>";
182+
for (int i = 0; i < rawUniqueID.length(); i++) {
183+
char currentChar = rawUniqueID.charAt(i);
184+
if (Character.isLetterOrDigit(currentChar)) {
185+
encodedUniqueID.append(currentChar);
186+
} else {
187+
if (parentheses.indexOf(currentChar) != -1) {
188+
encodedUniqueID.append("__");
189+
} else {
190+
encodedUniqueID.append('_');
191+
}
192+
}
193+
}
194+
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + encodedUniqueID.toString();
167195
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
168196
int parameterCount = invokedType.parameterCount();
169197
if (parameterCount > 0) {
@@ -252,6 +280,10 @@ public Constructor<?>[] run() {
252280
* is not found
253281
*/
254282
private Class<?> spinInnerClass() throws LambdaConversionException {
283+
Class<?> innerClass = MethodHandleNatives.findLambdaInSCC(lambdaClassName, targetClass);
284+
if (innerClass != null) {
285+
return innerClass;
286+
}
255287
String[] interfaces;
256288
String samIntf = samBase.getName().replace('.', '/');
257289
boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);

src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

+35-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
32+
2633
package java.lang.invoke;
2734

2835
import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -111,7 +118,22 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
111118
if (DUMP_CLASS_FILES) {
112119
className = makeDumpableClassName(className);
113120
}
114-
this.className = className;
121+
String rawUniqueID = className + invokerName + invokerType.toString() + lambdaForm.toString();
122+
StringBuilder encodedUniqueID = new StringBuilder();
123+
String parentheses = "(){}[]<>";
124+
for (int i = 0; i < rawUniqueID.length(); i++) {
125+
char currentChar = rawUniqueID.charAt(i);
126+
if (Character.isLetterOrDigit(currentChar)) {
127+
encodedUniqueID.append(currentChar);
128+
} else {
129+
if (parentheses.indexOf(currentChar) != -1) {
130+
encodedUniqueID.append("__");
131+
} else {
132+
encodedUniqueID.append('_');
133+
}
134+
}
135+
}
136+
this.className = className + "$" + encodedUniqueID.toString();
115137
this.lambdaForm = lambdaForm;
116138
this.invokerName = invokerName;
117139
this.invokerType = invokerType;
@@ -690,6 +712,10 @@ static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType
690712
if (pregenerated != null) return pregenerated; // pre-generated bytecode
691713

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

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

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

src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
2632
package java.lang.invoke;
2733

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

5056
static native void init(MemberName self, Object ref);
5157
static native void expand(MemberName self);
58+
static native Class<?> findLambdaFormInSCC(String classname, Class<?> hostClass);
59+
static native Class<?> findLambdaInSCC(String classname, Class<?> hostClass);
5260
static native MemberName resolve(MemberName self, Class<?> caller,
5361
boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
5462
static native int getMembers(Class<?> defc, String matchName, String matchSig,

0 commit comments

Comments
 (0)