8340280: Avoid calling MT.invokerType() when creating LambdaForms

Reviewed-by: liach, jvernee
This commit is contained in:
Claes Redestad 2024-09-18 07:01:13 +00:00
parent 147e30070d
commit d23c59e408
6 changed files with 48 additions and 43 deletions

View file

@ -143,7 +143,7 @@ abstract sealed class DelegatingMethodHandle extends MethodHandle
final int PRE_ACTION = hasPreAction ? nameCursor++ : -1;
final int NEXT_MH = customized ? -1 : nameCursor++;
final int REINVOKE = nameCursor++;
LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
LambdaForm.Name[] names = LambdaForm.invokeArguments(nameCursor - ARG_LIMIT, mtype);
assert(names.length == nameCursor);
names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
Object[] targetArgs;

View file

@ -250,11 +250,17 @@ sealed class DirectMethodHandle extends MethodHandle {
default: throw new InternalError("which="+which);
}
MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
if (doesAlloc)
mtypeWithArg = mtypeWithArg
.insertParameterTypes(0, Object.class) // insert newly allocated obj
.changeReturnType(void.class); // <init> returns void
MethodType mtypeWithArg;
if (doesAlloc) {
var ptypes = mtype.ptypes();
var newPtypes = new Class<?>[ptypes.length + 2];
newPtypes[0] = Object.class; // insert newly allocated obj
System.arraycopy(ptypes, 0, newPtypes, 1, ptypes.length);
newPtypes[newPtypes.length - 1] = MemberName.class;
mtypeWithArg = MethodType.methodType(void.class, newPtypes, true);
} else {
mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
}
MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED,
@ -270,7 +276,7 @@ sealed class DirectMethodHandle extends MethodHandle {
final int GET_MEMBER = nameCursor++;
final int CHECK_RECEIVER = (needsReceiverCheck ? nameCursor++ : -1);
final int LINKER_CALL = nameCursor++;
Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
assert(names.length == nameCursor);
if (doesAlloc) {
// names = { argx,y,z,... new C, init method }
@ -786,7 +792,7 @@ sealed class DirectMethodHandle extends MethodHandle {
final int LINKER_CALL = nameCursor++;
final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
final int RESULT = nameCursor-1; // either the call or the cast
Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
if (needsInit)
names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
if (needsCast && !isGetter)

View file

@ -314,14 +314,14 @@ class Invokers {
final int CHECK_TYPE = nameCursor++;
final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
final int LINKER_CALL = nameCursor++;
MethodType invokerFormType = mtype.invokerType();
MethodType invokerFormType = mtype;
if (isLinker) {
if (!customized)
invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
} else {
invokerFormType = invokerFormType.invokerType();
}
Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
Name[] names = invokeArguments(nameCursor - INARG_LIMIT, invokerFormType);
assert(names.length == nameCursor)
: Arrays.asList(mtype, customized, which, nameCursor, names.length);
if (MTYPE_ARG >= INARG_LIMIT) {
@ -390,11 +390,11 @@ class Invokers {
final int LINKER_CALL = nameCursor++;
Name[] names = new Name[LINKER_CALL + 1];
names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
names[THIS_VH] = argument(THIS_VH, BasicType.L_TYPE);
for (int i = 0; i < mtype.parameterCount(); i++) {
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
}
names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.L_TYPE);
names[UNBOUND_VH] = new Name(getFunction(NF_directVarHandleTarget), names[THIS_VH]);
@ -446,8 +446,8 @@ class Invokers {
final int LINKER_CALL = nameCursor++;
Name[] names = new Name[LINKER_CALL + 1];
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
names[THIS_MH] = argument(THIS_MH, BasicType.L_TYPE);
names[CALL_VH] = argument(CALL_VH, BasicType.L_TYPE);
for (int i = 0; i < mtype.parameterCount(); i++) {
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
}
@ -589,17 +589,16 @@ class Invokers {
final int CSITE_ARG = skipCallSite ? -1 : APPENDIX_ARG;
final int CALL_MH = skipCallSite ? APPENDIX_ARG : nameCursor++; // result of getTarget
final int LINKER_CALL = nameCursor++;
MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
assert(names.length == nameCursor);
assert(names[APPENDIX_ARG] != null);
Name[] names = arguments(nameCursor - INARG_LIMIT + 1, mtype);
assert(names.length == nameCursor && names[APPENDIX_ARG] == null);
names[APPENDIX_ARG] = argument(APPENDIX_ARG, BasicType.L_TYPE);
if (!skipCallSite)
names[CALL_MH] = new Name(getFunction(NF_getCallSiteTarget), names[CSITE_ARG]);
// (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
final int PREPEND_MH = 0, PREPEND_COUNT = 1;
Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
Object[] outArgs = new Object[OUTARG_LIMIT + PREPEND_COUNT];
System.arraycopy(names, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
// prepend MH argument:
System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
outArgs[PREPEND_MH] = names[CALL_MH];
names[LINKER_CALL] = new Name(mtype, outArgs);
lform = LambdaForm.create(INARG_LIMIT, names,

View file

@ -1636,6 +1636,16 @@ class LambdaForm {
names[i] = argument(i, basicType(types.parameterType(i)));
return names;
}
static Name[] invokeArguments(int extra, MethodType types) {
int length = types.parameterCount();
Name[] names = new Name[length + extra + 1];
names[0] = argument(0, L_TYPE);
for (int i = 0; i < length; i++)
names[i + 1] = argument(i + 1, basicType(types.parameterType(i)));
return names;
}
static final int INTERNED_ARGUMENT_LIMIT = 10;
private static final Name[][] INTERNED_ARGUMENTS
= new Name[ARG_TYPE_LIMIT][INTERNED_ARGUMENT_LIMIT];

View file

@ -810,8 +810,7 @@ abstract class MethodHandleImpl {
final int CALL_TARGET = nameCursor++;
assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative
MethodType lambdaType = basicType.invokerType();
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
BoundMethodHandle.SpeciesData data =
(GET_COUNTERS != -1) ? BoundMethodHandle.speciesData_LLLL()
@ -843,7 +842,7 @@ abstract class MethodHandleImpl {
invokeArgs[0] = names[SELECT_ALT];
names[CALL_TARGET] = new Name(basicType, invokeArgs);
lform = LambdaForm.create(lambdaType.parameterCount(), names, /*forceInline=*/true, Kind.GUARD);
lform = LambdaForm.create(basicType.parameterCount() + 1, names, /*forceInline=*/true, Kind.GUARD);
return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform);
}
@ -870,8 +869,6 @@ abstract class MethodHandleImpl {
* among catchException combinators with the same basic type.
*/
private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
MethodType lambdaType = basicType.invokerType();
LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
if (lform != null) {
return lform;
@ -890,7 +887,7 @@ abstract class MethodHandleImpl {
final int TRY_CATCH = nameCursor++;
final int UNBOX_RESULT = nameCursor++;
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
names[THIS_MH] = names[THIS_MH].withConstraint(data);
@ -919,7 +916,7 @@ abstract class MethodHandleImpl {
Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
lform = LambdaForm.create(lambdaType.parameterCount(), names, Kind.GUARD_WITH_CATCH);
lform = LambdaForm.create(basicType.parameterCount() + 1, names, Kind.GUARD_WITH_CATCH);
return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
}
@ -1733,8 +1730,6 @@ abstract class MethodHandleImpl {
* bytecode generation}.
*/
private static LambdaForm makeLoopForm(MethodType basicType, BasicType[] localVarTypes) {
MethodType lambdaType = basicType.invokerType();
final int THIS_MH = 0; // the BMH_LLL
final int ARG_BASE = 1; // start of incoming arguments
final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
@ -1749,7 +1744,7 @@ abstract class MethodHandleImpl {
LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_LOOP);
if (lform == null) {
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
names[THIS_MH] = names[THIS_MH].withConstraint(data);
@ -1777,7 +1772,7 @@ abstract class MethodHandleImpl {
names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
lform = basicType.form().setCachedLambdaForm(MethodTypeForm.LF_LOOP,
LambdaForm.create(lambdaType.parameterCount(), names, Kind.LOOP));
LambdaForm.create(basicType.parameterCount() + 1, names, Kind.LOOP));
}
// BOXED_ARGS is the index into the names array where the loop idiom starts
@ -1966,8 +1961,6 @@ abstract class MethodHandleImpl {
* forms among tryFinally combinators with the same basic type.
*/
private static LambdaForm makeTryFinallyForm(MethodType basicType) {
MethodType lambdaType = basicType.invokerType();
LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_TF);
if (lform != null) {
return lform;
@ -1985,7 +1978,7 @@ abstract class MethodHandleImpl {
final int TRY_FINALLY = nameCursor++;
final int UNBOX_RESULT = nameCursor++;
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
names[THIS_MH] = names[THIS_MH].withConstraint(data);
@ -2011,7 +2004,7 @@ abstract class MethodHandleImpl {
Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_FINALLY]};
names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
lform = LambdaForm.create(lambdaType.parameterCount(), names, Kind.TRY_FINALLY);
lform = LambdaForm.create(basicType.parameterCount() + 1, names, Kind.TRY_FINALLY);
return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_TF, lform);
}
@ -2055,7 +2048,6 @@ abstract class MethodHandleImpl {
}
private static LambdaForm makeCollectorForm(MethodType basicType, Class<?> arrayType) {
MethodType lambdaType = basicType.invokerType();
int parameterCount = basicType.parameterCount();
// Only share the lambda form for empty arrays and reference types.
@ -2088,7 +2080,7 @@ abstract class MethodHandleImpl {
final int STORE_ELEMENT_LIMIT = STORE_ELEMENT_BASE + parameterCount;
nameCursor = STORE_ELEMENT_LIMIT;
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_L();
names[THIS_MH] = names[THIS_MH].withConstraint(data);
@ -2106,7 +2098,7 @@ abstract class MethodHandleImpl {
names[CALL_NEW_ARRAY], storeIndex, names[argCursor]);
}
LambdaForm lform = LambdaForm.create(lambdaType.parameterCount(), names, CALL_NEW_ARRAY, Kind.COLLECTOR);
LambdaForm lform = LambdaForm.create(basicType.parameterCount() + 1, names, CALL_NEW_ARRAY, Kind.COLLECTOR);
if (isSharedLambdaForm) {
lform = basicType.form().setCachedLambdaForm(MethodTypeForm.LF_COLLECTOR, lform);
}
@ -2169,8 +2161,6 @@ abstract class MethodHandleImpl {
private static LambdaForm makeTableSwitchForm(MethodType basicType, BoundMethodHandle.SpeciesData data,
int numCases) {
MethodType lambdaType = basicType.invokerType();
// We need to cache based on the basic type X number of cases,
// since the number of cases is used when generating bytecode.
// This also means that we can't use the cache in MethodTypeForm,
@ -2202,7 +2192,7 @@ abstract class MethodHandleImpl {
final int FIELD_UNBOX_RESULT = fieldCursor++;
final int FIELD_CASES = fieldCursor++;
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
Name[] names = invokeArguments(nameCursor - ARG_LIMIT, basicType);
names[THIS_MH] = names[THIS_MH].withConstraint(data);
names[GET_DEFAULT_CASE] = new Name(data.getterFunction(FIELD_DEFAULT_CASE), names[THIS_MH]);
@ -2231,7 +2221,7 @@ abstract class MethodHandleImpl {
names[UNBOXED_RESULT] = new Name(invokeBasic, unboxArgs);
}
lform = LambdaForm.create(lambdaType.parameterCount(), names, Kind.TABLE_SWITCH);
lform = LambdaForm.create(basicType.parameterCount() + 1, names, Kind.TABLE_SWITCH);
LambdaForm prev = TableSwitchCacheKey.CACHE.putIfAbsent(key, lform);
return prev != null ? prev : lform;
}

View file

@ -108,7 +108,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
final int GET_NEP = nameCursor++;
final int LINKER_CALL = nameCursor++;
LambdaForm.Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
LambdaForm.Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
assert (names.length == nameCursor);
names[GET_NEP] = new LambdaForm.Name(Lazy.NF_internalNativeEntryPoint, names[NMH_THIS]);