From 5770205d90067bf5252ccb07c8f5f69871777bcf Mon Sep 17 00:00:00 2001 From: Nathan Henderson Date: Mon, 24 Jun 2024 14:26:58 -0700 Subject: [PATCH] wip Stable and unique Lambda and LambdaForm class names --- .../invoke/InnerClassLambdaMetafactory.java | 15 ++++++++++++- .../lang/invoke/InvokerBytecodeGenerator.java | 22 ++++++++++++++++++- .../java/lang/invoke/MethodHandleNatives.java | 1 + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 36ff5debbfc..c2a51c75088 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -163,7 +163,16 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, implMethodName = implInfo.getName(); implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); constructorType = invokedType.changeReturnType(Void.TYPE); - lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); + int uniqueID = targetClass.getName().hashCode() + ^ invokedType.toString().hashCode() + ^ samMethodName.hashCode() + ^ samMethodType.toString().hashCode() + ^ instantiatedMethodType.toString().hashCode() + ^ implMethodClassName.hashCode() + ^ implMethodName.hashCode() + ^ implMethodDesc.hashCode(); + uniqueID &= 0x7fffffff; + lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + uniqueID; cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { @@ -252,6 +261,10 @@ public Constructor[] run() { * is not found */ private Class spinInnerClass() throws LambdaConversionException { + Class innerClass = MethodHandleNatives.findInSCC(lambdaClassName, targetClass); + if (innerClass != null) { + return innerClass; + } String[] interfaces; String samIntf = samBase.getName().replace('.', '/'); boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase); diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 2ff3cab04a4..238caed2f68 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -38,6 +38,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.invoke.LambdaForm.BasicType; +import java.lang.invoke.LambdaForm.Name; +import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -111,7 +114,12 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = className; + int uniqueID = lambdaForm.toString().hashCode() + ^ className.hashCode() + ^ invokerName.hashCode() + ^ invokerType.toString().hashCode(); + uniqueID &= 0x7fffffff; + this.className = className + "$" + uniqueID; this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; @@ -690,6 +698,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.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateCustomizedCodeBytes()); } @@ -1766,6 +1778,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.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } @@ -1825,6 +1841,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.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 3e872414b6c..92e3fb290cf 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -49,6 +49,7 @@ private MethodHandleNatives() { } // static only static native void init(MemberName self, Object ref); static native void expand(MemberName self); + static native Class findInSCC(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,