case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
default: throw new InternalError();
}
LambdaForm lform;
if (isCached) {
lform = mtype.form().cachedLambdaForm(which);
if (lform != null) return lform;
}
// exactInvokerForm (Object,Object)Object
// link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
final int THIS_MH = 0;
final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
final int ARG_BASE = CALL_MH + 1;
final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
int nameCursor = OUTARG_LIMIT;
final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
final int CHECK_TYPE = nameCursor++;
final int LINKER_CALL = nameCursor++;
MethodType invokerFormType = mtype.invokerType();
if (isLinker) {
if (!customized)
invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
} else {
invokerFormType = invokerFormType.invokerType();
}
Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
assert(names.length == nameCursor)
: Arrays.asList(mtype, customized, which, nameCursor, names.length);
if (MTYPE_ARG >= INARG_LIMIT) {
assert(names[MTYPE_ARG] == null);
NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
// else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
}
// Make the final call. If isGeneric, then prepend the result of type checking.
MethodType outCallType = mtype.basicType();
Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
if (!isGeneric) {
names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
// mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
} else {
names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
// mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
outArgs[0] = names[CHECK_TYPE];
}
names[LINKER_CALL] = new Name(outCallType, outArgs);
lform = new LambdaForm(debugName, INARG_LIMIT, names);
if (isLinker)
lform.compileToBytecode(); // JVM needs a real methodOop
if (isCached)
lform = mtype.form().setCachedLambdaForm(which, lform);
return lform;
}