< prev index next >
src/java.base/share/classes/java/lang/invoke/LambdaForm.java
Print this page
rev 15353 : 8164044: Generate the corresponding BoundMethodHandle to all generated DirectMethodHandles
Reviewed-by: vlivanov, mhaupt
*** 39,48 ****
--- 39,49 ----
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,134 ****
--- 126,136 ----
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,300 ****
assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
return true;
}
}
LambdaForm(String debugName,
int arity, Name[] names, int result) {
! this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null);
}
LambdaForm(String debugName,
int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
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;
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);
}
LambdaForm(String debugName,
int arity, Name[] names, boolean forceInline) {
! this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null);
}
LambdaForm(String debugName,
Name[] formals, Name[] temps, Name result) {
this(debugName,
formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
--- 266,341 ----
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, 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, Kind.GENERIC);
}
LambdaForm(String debugName,
int arity, Name[] names, boolean forceInline) {
! 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,332 ****
--- 364,374 ----
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,403 ****
return true;
}
/** Customize LambdaForm for a particular MethodHandle */
LambdaForm customize(MethodHandle mh) {
! LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
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.
--- 435,445 ----
return true;
}
/** Customize LambdaForm for a particular MethodHandle */
LambdaForm customize(MethodHandle 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,802 ****
} 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();
--- 813,822 ----
< prev index next >