< prev index next >
src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
Print this page
rev 15353 : 8164044: Generate corresponding simple DelegatingMethodHandles when generating a DirectMethodHandle at link time
Reviewed-by: vlivanov, mhaupt, shade
@@ -44,10 +44,11 @@
import java.util.HashMap;
import java.util.stream.Stream;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.BasicType.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
/**
* Code generation backend for LambdaForm.
@@ -123,13 +124,19 @@
localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
}
}
/** For generating customized code for a single LambdaForm. */
- InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
+ private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
+ this(className, form.debugName, form, invokerType);
+ }
+
+ /** For generating customized code for a single LambdaForm. */
+ InvokerBytecodeGenerator(String className, String invokerName,
+ LambdaForm form, MethodType invokerType) {
this(form, form.names.length,
- className, form.debugName, invokerType);
+ className, invokerName, invokerType);
// Create an array to map name indexes to locals indexes.
Name[] names = form.names;
for (int i = 0, index = 0; i < localsMap.length; i++) {
localsMap[i] = index;
if (i < names.length) {
@@ -595,14 +602,46 @@
else if (c == MethodHandle.class) return MH;
assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName();
return c.getName().replace('.', '/');
}
+ private static MemberName resolveFrom(String name, MethodType type, Class<?> holder) {
+ MemberName member = new MemberName(holder, name, type, REF_invokeStatic);
+ MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder);
+
+ return resolvedMember;
+ }
+
+ private static MemberName lookupPregenerated(LambdaForm form) {
+ if (form.customized != null) {
+ // No pre-generated version for customized LF
+ return null;
+ }
+ MethodType invokerType = form.methodType();
+ String name = form.kind.methodName;
+ switch (form.kind) {
+ case BOUND_REINVOKER: {
+ name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature();
+ return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
+ }
+ case DELEGATE: return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
+ case DIRECT_INVOKE_INTERFACE: // fall-through
+ case DIRECT_INVOKE_SPECIAL: // fall-through
+ case DIRECT_INVOKE_STATIC: // fall-through
+ case DIRECT_INVOKE_STATIC_INIT: // fall-through
+ case DIRECT_INVOKE_VIRTUAL: return resolveFrom(name, invokerType, DirectMethodHandle.Holder.class);
+ }
+ return null;
+ }
+
/**
* Generate customized bytecode for a given LambdaForm.
*/
static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
+ MemberName pregenerated = lookupPregenerated(form);
+ if (pregenerated != null) return pregenerated; // pre-generated bytecode
+
InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
return g.loadMethod(g.generateCustomizedCodeBytes());
}
/** Generates code to check that actual receiver and LambdaForm matches */
< prev index next >