8257164: Share LambdaForms for VH linkers/invokers

Reviewed-by: redestad, kvn, psandoz
This commit is contained in:
Vladimir Ivanov 2020-12-02 21:47:27 +00:00
parent 3e89981d98
commit 7104400ad8
3 changed files with 38 additions and 27 deletions

View file

@ -139,7 +139,7 @@ class Invokers {
MethodType mtype = targetType; MethodType mtype = targetType;
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class); MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
LambdaForm lform = varHandleMethodInvokerHandleForm(ak, mtype, isExact); LambdaForm lform = varHandleMethodInvokerHandleForm(mtype, isExact);
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal()); VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
@ -346,20 +346,22 @@ class Invokers {
} }
static MemberName varHandleInvokeLinkerMethod(VarHandle.AccessMode ak, MethodType mtype) { static MemberName varHandleInvokeLinkerMethod(MethodType mtype) {
LambdaForm lform; if (mtype.parameterSlotCount() > MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
lform = varHandleMethodGenericLinkerHandleForm(ak, mtype);
} else {
// TODO
throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount()); throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
} }
LambdaForm lform = varHandleMethodGenericLinkerHandleForm(mtype);
return lform.vmentry; return lform.vmentry;
} }
private static LambdaForm varHandleMethodGenericLinkerHandleForm(VarHandle.AccessMode ak, private static LambdaForm varHandleMethodGenericLinkerHandleForm(MethodType mtype) {
MethodType mtype) { mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
// TODO Cache form?
int which = MethodTypeForm.LF_VH_GEN_LINKER;
LambdaForm lform = mtype.form().cachedLambdaForm(which);
if (lform != null) {
return lform;
}
final int THIS_VH = 0; final int THIS_VH = 0;
final int ARG_BASE = THIS_VH + 1; final int ARG_BASE = THIS_VH + 1;
@ -396,19 +398,26 @@ class Invokers {
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class) MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
.basicType(); .basicType();
names[LINKER_CALL] = new Name(outCallType, outArgs); names[LINKER_CALL] = new Name(outCallType, outArgs);
LambdaForm lform = new LambdaForm(ARG_LIMIT + 1, names, VARHANDLE_LINKER); lform = new LambdaForm(ARG_LIMIT + 1, names, VARHANDLE_LINKER);
if (LambdaForm.debugNames()) { if (LambdaForm.debugNames()) {
String name = ak.methodName() + ":VarHandle_invoke_MT_" + String name = "VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype));
shortenSignature(basicTypeSignature(mtype));
LambdaForm.associateWithDebugName(lform, name); LambdaForm.associateWithDebugName(lform, name);
} }
lform.compileToBytecode(); lform.compileToBytecode();
lform = mtype.form().setCachedLambdaForm(which, lform);
return lform; return lform;
} }
private static LambdaForm varHandleMethodInvokerHandleForm(VarHandle.AccessMode ak, private static LambdaForm varHandleMethodInvokerHandleForm(MethodType mtype, boolean isExact) {
MethodType mtype, boolean isExact) { mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
// TODO Cache form?
int which = (isExact ? MethodTypeForm.LF_VH_EX_INVOKER : MethodTypeForm.LF_VH_GEN_INVOKER);
LambdaForm lform = mtype.form().cachedLambdaForm(which);
if (lform != null) {
return lform;
}
final int THIS_MH = 0; final int THIS_MH = 0;
final int CALL_VH = THIS_MH + 1; final int CALL_VH = THIS_MH + 1;
@ -448,17 +457,18 @@ class Invokers {
} }
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class) MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
.basicType(); .basicType();
names[LINKER_CALL] = new Name(outCallType, outArgs); names[LINKER_CALL] = new Name(outCallType, outArgs);
Kind kind = isExact ? VARHANDLE_EXACT_INVOKER : VARHANDLE_INVOKER; Kind kind = isExact ? VARHANDLE_EXACT_INVOKER : VARHANDLE_INVOKER;
LambdaForm lform = new LambdaForm(ARG_LIMIT, names, kind); lform = new LambdaForm(ARG_LIMIT, names, kind);
if (LambdaForm.debugNames()) { if (LambdaForm.debugNames()) {
String name = ak.methodName() + String name = (isExact ? "VarHandle_exactInvoker_" : "VarHandle_invoker_") + shortenSignature(basicTypeSignature(mtype));
(isExact ? ":VarHandle_exactInvoker_" : ":VarHandle_invoker_") +
shortenSignature(basicTypeSignature(mtype));
LambdaForm.associateWithDebugName(lform, name); LambdaForm.associateWithDebugName(lform, name);
} }
lform.prepare(); lform.prepare();
lform = mtype.form().setCachedLambdaForm(which, lform);
return lform; return lform;
} }
@ -473,12 +483,10 @@ class Invokers {
// Test for exact match on invoker types // Test for exact match on invoker types
// TODO match with erased types and add cast of return value to lambda form // TODO match with erased types and add cast of return value to lambda form
MethodHandle mh = handle.getMethodHandle(ad.mode); MethodHandle mh = handle.getMethodHandle(ad.mode);
if (mh.type() == ad.symbolicMethodTypeInvoker) { if (mh.type() != ad.symbolicMethodTypeInvoker) {
return mh;
}
else {
return mh.asType(ad.symbolicMethodTypeInvoker); return mh.asType(ad.symbolicMethodTypeInvoker);
} }
return mh;
} }
@ForceInline @ForceInline

View file

@ -578,7 +578,7 @@ class MethodHandleNatives {
// Fall back to lambda form linkage if guard method is not available // Fall back to lambda form linkage if guard method is not available
// TODO Optionally log fallback ? // TODO Optionally log fallback ?
} }
return Invokers.varHandleInvokeLinkerMethod(ak, mtype); return Invokers.varHandleInvokeLinkerMethod(mtype);
} }
static String getVarHandleGuardMethodName(MethodType guardType) { static String getVarHandleGuardMethodName(MethodType guardType) {
String prefix = "guard_"; String prefix = "guard_";

View file

@ -87,7 +87,10 @@ final class MethodTypeForm {
LF_LOOP = 19, // loop LF_LOOP = 19, // loop
LF_INVSPECIAL_IFC = 20, // DMH invokeSpecial of (private) interface method LF_INVSPECIAL_IFC = 20, // DMH invokeSpecial of (private) interface method
LF_INVNATIVE = 21, // NMH invokeNative LF_INVNATIVE = 21, // NMH invokeNative
LF_LIMIT = 22; LF_VH_EX_INVOKER = 22, // VarHandle exact invoker
LF_VH_GEN_INVOKER = 23, // VarHandle generic invoker
LF_VH_GEN_LINKER = 24, // VarHandle generic linker
LF_LIMIT = 25;
/** Return the type corresponding uniquely (1-1) to this MT-form. /** Return the type corresponding uniquely (1-1) to this MT-form.
* It might have any primitive returns or arguments, but will have no references except Object. * It might have any primitive returns or arguments, but will have no references except Object.