Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8287442: Reduce list to array conversions in java.lang.invoke.MethodH…
…andles

Reviewed-by: jvernee
  • Loading branch information
cl4es committed Jun 8, 2022
1 parent 5c39a36 commit ecf0078
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 40 deletions.
Expand Up @@ -973,7 +973,7 @@ static MethodHandle throwException(MethodType type) {
int arity = type.parameterCount();
if (arity > 1) {
MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
mh = MethodHandles.dropArguments(mh, 1, Arrays.copyOfRange(type.parameterArray(), 1, arity));
mh = MethodHandles.dropArgumentsTrusted(mh, 1, Arrays.copyOfRange(type.ptypes(), 1, arity));
return mh;
}
return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true);
Expand Down Expand Up @@ -1941,7 +1941,7 @@ static Object iterateNext(Iterator<?> it) {
*
* @return a handle on the constructed {@code try-finally} block.
*/
static MethodHandle makeTryFinally(MethodHandle target, MethodHandle cleanup, Class<?> rtype, List<Class<?>> argTypes) {
static MethodHandle makeTryFinally(MethodHandle target, MethodHandle cleanup, Class<?> rtype, Class<?>[] argTypes) {
MethodType type = MethodType.methodType(rtype, argTypes);
LambdaForm form = makeTryFinallyForm(type.basicType());

Expand Down
77 changes: 40 additions & 37 deletions src/java.base/share/classes/java/lang/invoke/MethodHandles.java
Expand Up @@ -5104,7 +5104,7 @@ private static MethodHandle identityOrVoid(Class<?> type) {
*/
public static MethodHandle empty(MethodType type) {
Objects.requireNonNull(type);
return dropArguments(zero(type.returnType()), 0, type.parameterList());
return dropArgumentsTrusted(zero(type.returnType()), 0, type.ptypes());
}

private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
Expand Down Expand Up @@ -5263,14 +5263,10 @@ private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCoun
* or if the new method handle's type would have too many parameters
*/
public static MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
return dropArguments0(target, pos, copyTypes(valueTypes.toArray()));
return dropArgumentsTrusted(target, pos, valueTypes.toArray(new Class<?>[0]).clone());
}

private static List<Class<?>> copyTypes(Object[] array) {
return Arrays.asList(Arrays.copyOf(array, array.length, Class[].class));
}

private static MethodHandle dropArguments0(MethodHandle target, int pos, List<Class<?>> valueTypes) {
static MethodHandle dropArgumentsTrusted(MethodHandle target, int pos, Class<?>[] valueTypes) {
MethodType oldType = target.type(); // get NPE
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
Expand All @@ -5285,8 +5281,8 @@ private static MethodHandle dropArguments0(MethodHandle target, int pos, List<Cl
return result;
}

private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
int dropped = valueTypes.size();
private static int dropArgumentChecks(MethodType oldType, int pos, Class<?>[] valueTypes) {
int dropped = valueTypes.length;
MethodType.checkSlotCount(dropped);
int outargs = oldType.parameterCount();
int inargs = outargs + dropped;
Expand Down Expand Up @@ -5344,51 +5340,59 @@ private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/
public static MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
return dropArguments0(target, pos, copyTypes(valueTypes));
return dropArgumentsTrusted(target, pos, valueTypes.clone());
}

/* Convenience overloads for trusting internal low-arity call-sites */
static MethodHandle dropArguments(MethodHandle target, int pos, Class<?> valueType1) {
return dropArgumentsTrusted(target, pos, new Class<?>[] { valueType1 });
}
static MethodHandle dropArguments(MethodHandle target, int pos, Class<?> valueType1, Class<?> valueType2) {
return dropArgumentsTrusted(target, pos, new Class<?>[] { valueType1, valueType2 });
}

// private version which allows caller some freedom with error handling
private static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos,
private static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, Class<?>[] newTypes, int pos,
boolean nullOnFailure) {
newTypes = copyTypes(newTypes.toArray());
List<Class<?>> oldTypes = target.type().parameterList();
int match = oldTypes.size();
Class<?>[] oldTypes = target.type().ptypes();
int match = oldTypes.length;
if (skip != 0) {
if (skip < 0 || skip > match) {
throw newIllegalArgumentException("illegal skip", skip, target);
}
oldTypes = oldTypes.subList(skip, match);
oldTypes = Arrays.copyOfRange(oldTypes, skip, match);
match -= skip;
}
List<Class<?>> addTypes = newTypes;
int add = addTypes.size();
Class<?>[] addTypes = newTypes;
int add = addTypes.length;
if (pos != 0) {
if (pos < 0 || pos > add) {
throw newIllegalArgumentException("illegal pos", pos, newTypes);
throw newIllegalArgumentException("illegal pos", pos, Arrays.toString(newTypes));
}
addTypes = addTypes.subList(pos, add);
addTypes = Arrays.copyOfRange(addTypes, pos, add);
add -= pos;
assert(addTypes.size() == add);
assert(addTypes.length == add);
}
// Do not add types which already match the existing arguments.
if (match > add || !oldTypes.equals(addTypes.subList(0, match))) {
if (match > add || !Arrays.equals(oldTypes, 0, oldTypes.length, addTypes, 0, match)) {
if (nullOnFailure) {
return null;
}
throw newIllegalArgumentException("argument lists do not match", oldTypes, newTypes);
throw newIllegalArgumentException("argument lists do not match",
Arrays.toString(oldTypes), Arrays.toString(newTypes));
}
addTypes = addTypes.subList(match, add);
addTypes = Arrays.copyOfRange(addTypes, match, add);
add -= match;
assert(addTypes.size() == add);
assert(addTypes.length == add);
// newTypes: ( P*[pos], M*[match], A*[add] )
// target: ( S*[skip], M*[match] )
MethodHandle adapter = target;
if (add > 0) {
adapter = dropArguments0(adapter, skip+ match, addTypes);
adapter = dropArgumentsTrusted(adapter, skip+ match, addTypes);
}
// adapter: (S*[skip], M*[match], A*[add] )
if (pos > 0) {
adapter = dropArguments0(adapter, skip, newTypes.subList(0, pos));
adapter = dropArgumentsTrusted(adapter, skip, Arrays.copyOfRange(newTypes, 0, pos));
}
// adapter: (S*[skip], P*[pos], M*[match], A*[add] )
return adapter;
Expand Down Expand Up @@ -5452,7 +5456,7 @@ private static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip,
public static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) {
Objects.requireNonNull(target);
Objects.requireNonNull(newTypes);
return dropArgumentsToMatch(target, skip, newTypes, pos, false);
return dropArgumentsToMatch(target, skip, newTypes.toArray(new Class<?>[0]).clone(), pos, false);
}

/**
Expand Down Expand Up @@ -5771,7 +5775,7 @@ private static MethodType collectArgumentsChecks(MethodHandle target, int pos, M
MethodType targetType = target.type();
MethodType filterType = filter.type();
Class<?> rtype = filterType.returnType();
List<Class<?>> filterArgs = filterType.parameterList();
Class<?>[] filterArgs = filterType.ptypes();
if (pos < 0 || (rtype == void.class && pos > targetType.parameterCount()) ||
(rtype != void.class && pos >= targetType.parameterCount())) {
throw newIllegalArgumentException("position is out of range for target", target, pos);
Expand All @@ -5782,7 +5786,7 @@ private static MethodType collectArgumentsChecks(MethodHandle target, int pos, M
if (rtype != targetType.parameterType(pos)) {
throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
}
return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs);
return targetType.dropParameterTypes(pos, pos + 1).insertParameterTypes(pos, filterArgs);
}

/**
Expand Down Expand Up @@ -6240,8 +6244,8 @@ public static MethodHandle guardWithTest(MethodHandle test,
throw misMatchedTypes("target and fallback types", ttype, ftype);
if (gtype.returnType() != boolean.class)
throw newIllegalArgumentException("guard type is not a predicate "+gtype);
List<Class<?>> targs = ttype.parameterList();
test = dropArgumentsToMatch(test, 0, targs, 0, true);

test = dropArgumentsToMatch(test, 0, ttype.ptypes(), 0, true);
if (test == null) {
throw misMatchedTypes("target and test types", ttype, gtype);
}
Expand Down Expand Up @@ -6314,7 +6318,7 @@ public static MethodHandle catchException(MethodHandle target,
throw newIllegalArgumentException("handler does not accept exception type "+exType);
if (htype.returnType() != ttype.returnType())
throw misMatchedTypes("target and handler return types", ttype, htype);
handler = dropArgumentsToMatch(handler, 1, ttype.parameterList(), 0, true);
handler = dropArgumentsToMatch(handler, 1, ttype.ptypes(), 0, true);
if (handler == null) {
throw misMatchedTypes("target and handler types", ttype, htype);
}
Expand Down Expand Up @@ -6689,7 +6693,6 @@ public static MethodHandle loop(MethodHandle[]... clauses) {
final List<Class<?>> commonParameterSequence = new ArrayList<>(commonPrefix);
commonParameterSequence.addAll(commonSuffix);
loopChecks2(step, pred, fini, commonParameterSequence);

// Step 3: fill in omitted functions.
for (int i = 0; i < nclauses; ++i) {
Class<?> t = iterationVariableTypes.get(i);
Expand All @@ -6700,7 +6703,7 @@ public static MethodHandle loop(MethodHandle[]... clauses) {
step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
}
if (pred.get(i) == null) {
pred.set(i, dropArguments0(constant(boolean.class, true), 0, commonParameterSequence));
pred.set(i, dropArguments(constant(boolean.class, true), 0, commonParameterSequence));
}
if (fini.get(i) == null) {
fini.set(i, empty(methodType(t, commonParameterSequence)));
Expand Down Expand Up @@ -6799,7 +6802,7 @@ private static List<MethodHandle> fillParameterTypes(List<MethodHandle> hs, fina
return hs.stream().map(h -> {
int pc = h.type().parameterCount();
int tpsize = targetParams.size();
return pc < tpsize ? dropArguments0(h, pc, targetParams.subList(pc, tpsize)) : h;
return pc < tpsize ? dropArguments(h, pc, targetParams.subList(pc, tpsize)) : h;
}).toList();
}

Expand Down Expand Up @@ -7743,15 +7746,15 @@ static MethodHandle swapArguments(MethodHandle mh, int i, int j) {
* @since 9
*/
public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) {
List<Class<?>> targetParamTypes = target.type().parameterList();
Class<?>[] targetParamTypes = target.type().ptypes();
Class<?> rtype = target.type().returnType();

tryFinallyChecks(target, cleanup);

// Match parameter lists: if the cleanup has a shorter parameter list than the target, add ignored arguments.
// The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
// target parameter list.
cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0);
cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0, false);

// Ensure that the intrinsic type checks the instance thrown by the
// target against the first parameter of cleanup
Expand Down
Expand Up @@ -509,7 +509,7 @@ private static MethodHandle generateMHInlineCopy(MethodType mt, String[] constan
// assembled bottom-up, which makes the code arguably hard to read.

// Drop all remaining parameter types, leave only helper arguments:
MethodHandle mh = MethodHandles.dropArguments(newString(), 2, ptypes);
MethodHandle mh = MethodHandles.dropArgumentsTrusted(newString(), 2, ptypes);

// Calculate the initialLengthCoder value by looking at all constant values and summing up
// their lengths and adjusting the encoded coder bit if needed
Expand Down

0 comments on commit ecf0078

Please sign in to comment.