< prev index next >
src/java.base/share/classes/java/lang/invoke/LambdaForm.java
Print this page
rev 15353 : 8164044: Generate corresponding simple DelegatingMethodHandles when generating a DirectMethodHandle at link time
Reviewed-by: vlivanov, mhaupt, shade
@@ -39,10 +39,11 @@
import java.util.HashMap;
import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
import static java.lang.invoke.MethodHandleStatics.*;
+import java.util.Objects;
/**
* The symbolic, non-executable form of a method handle's invocation semantics.
* It consists of a series of names.
* The first N (N=arity) names are parameters,
@@ -125,10 +126,11 @@
final int result;
final boolean forceInline;
final MethodHandle customized;
@Stable final Name[] names;
final String debugName;
+ final Kind kind;
MemberName vmentry; // low-level behavior, or null if not yet prepared
private boolean isCompiled;
// Either a LambdaForm cache (managed by LambdaFormEditor) or a link to uncustomized version (for customized LF)
volatile Object transformCache;
@@ -264,37 +266,76 @@
assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
return true;
}
}
+ enum Kind {
+ GENERIC(""),
+ BOUND_REINVOKER("BMH.reinvoke"),
+ REINVOKER("MH.reinvoke"),
+ DELEGATE("MH.delegate"),
+ DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
+ DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
+ DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
+ DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
+ DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
+ DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
+
+ final String defaultLambdaName;
+ final String methodName;
+
+ private Kind(String defaultLambdaName) {
+ this.defaultLambdaName = defaultLambdaName;
+ int p = defaultLambdaName.indexOf('.');
+ if (p > -1) {
+ this.methodName = defaultLambdaName.substring(p + 1);
+ } else {
+ this.methodName = defaultLambdaName;
+ }
+ }
+ }
+
LambdaForm(String debugName,
int arity, Name[] names, int result) {
- this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null);
+ this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
+ }
+ LambdaForm(String debugName,
+ int arity, Name[] names, int result, Kind kind) {
+ this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, kind);
}
LambdaForm(String debugName,
int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
+ this(debugName, arity, names, result, forceInline, customized, Kind.GENERIC);
+ }
+ LambdaForm(String debugName,
+ int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) {
assert(namesOK(arity, names));
this.arity = arity;
this.result = fixResult(result, names);
this.names = names.clone();
this.debugName = fixDebugName(debugName);
this.forceInline = forceInline;
this.customized = customized;
+ this.kind = kind;
int maxOutArity = normalize();
if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
// Cannot use LF interpreter on very high arity expressions.
assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
compileToBytecode();
}
}
LambdaForm(String debugName,
int arity, Name[] names) {
- this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
+ this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
}
LambdaForm(String debugName,
int arity, Name[] names, boolean forceInline) {
- this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null);
+ this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
+ }
+ LambdaForm(String debugName,
+ int arity, Name[] names, boolean forceInline, Kind kind) {
+ this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind);
}
LambdaForm(String debugName,
Name[] formals, Name[] temps, Name result) {
this(debugName,
formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
@@ -323,10 +364,11 @@
this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
this.names = buildEmptyNames(arity, mt, result == -1);
this.debugName = "LF.zero";
this.forceInline = true;
this.customized = null;
+ this.kind = Kind.GENERIC;
assert(nameRefsAreLegal());
assert(isEmpty());
String sig = null;
assert(isValidSignature(sig = basicTypeSignature()));
assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
@@ -393,11 +435,11 @@
return true;
}
/** Customize LambdaForm for a particular MethodHandle */
LambdaForm customize(MethodHandle mh) {
- LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
+ LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh, kind);
if (COMPILE_THRESHOLD >= 0 && isCompiled) {
// If shared LambdaForm has been compiled, compile customized version as well.
customForm.compileToBytecode();
}
customForm.transformCache = this; // LambdaFormEditor should always use uncustomized form.
@@ -771,32 +813,10 @@
} catch (Error | Exception e) {
throw newInternalError(this.toString(), e);
}
}
- /**
- * Generate optimizable bytecode for this form after first looking for a
- * pregenerated version in a specified class.
- */
- void compileToBytecode(Class<?> lookupClass) {
- if (vmentry != null && isCompiled) {
- return; // already compiled somehow
- }
- MethodType invokerType = methodType();
- assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
- int dot = debugName.indexOf('.');
- String methodName = (dot > 0) ? debugName.substring(dot + 1) : debugName;
- MemberName member = new MemberName(lookupClass, methodName, invokerType, REF_invokeStatic);
- MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, lookupClass);
- if (resolvedMember != null) {
- vmentry = resolvedMember;
- isCompiled = true;
- } else {
- compileToBytecode();
- }
- }
-
private static void computeInitialPreparedForms() {
// Find all predefined invokers and associate them with canonical empty lambda forms.
for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
if (!m.isStatic() || !m.isPackage()) continue;
MethodType mt = m.getMethodType();
< prev index next >