8287442: Reduce list to array conversions in java.lang.invoke.MethodHandles
Reviewed-by: jvernee
This commit is contained in:
parent
5c39a36641
commit
ecf00785f2
src/java.base/share/classes/java/lang/invoke
@ -973,7 +973,7 @@ abstract class MethodHandleImpl {
|
|||||||
int arity = type.parameterCount();
|
int arity = type.parameterCount();
|
||||||
if (arity > 1) {
|
if (arity > 1) {
|
||||||
MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
|
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 mh;
|
||||||
}
|
}
|
||||||
return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true);
|
return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true);
|
||||||
@ -1941,7 +1941,7 @@ abstract class MethodHandleImpl {
|
|||||||
*
|
*
|
||||||
* @return a handle on the constructed {@code try-finally} block.
|
* @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);
|
MethodType type = MethodType.methodType(rtype, argTypes);
|
||||||
LambdaForm form = makeTryFinallyForm(type.basicType());
|
LambdaForm form = makeTryFinallyForm(type.basicType());
|
||||||
|
|
||||||
|
@ -5104,7 +5104,7 @@ assert((int)twice.invokeExact(21) == 42);
|
|||||||
*/
|
*/
|
||||||
public static MethodHandle empty(MethodType type) {
|
public static MethodHandle empty(MethodType type) {
|
||||||
Objects.requireNonNull(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];
|
private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
|
||||||
@ -5263,14 +5263,10 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
|
|||||||
* or if the new method handle's type would have too many parameters
|
* or if the new method handle's type would have too many parameters
|
||||||
*/
|
*/
|
||||||
public static MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
|
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) {
|
static MethodHandle dropArgumentsTrusted(MethodHandle target, int pos, Class<?>[] valueTypes) {
|
||||||
return Arrays.asList(Arrays.copyOf(array, array.length, Class[].class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MethodHandle dropArguments0(MethodHandle target, int pos, List<Class<?>> valueTypes) {
|
|
||||||
MethodType oldType = target.type(); // get NPE
|
MethodType oldType = target.type(); // get NPE
|
||||||
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
|
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
|
||||||
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
|
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
|
||||||
@ -5285,8 +5281,8 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
|
private static int dropArgumentChecks(MethodType oldType, int pos, Class<?>[] valueTypes) {
|
||||||
int dropped = valueTypes.size();
|
int dropped = valueTypes.length;
|
||||||
MethodType.checkSlotCount(dropped);
|
MethodType.checkSlotCount(dropped);
|
||||||
int outargs = oldType.parameterCount();
|
int outargs = oldType.parameterCount();
|
||||||
int inargs = outargs + dropped;
|
int inargs = outargs + dropped;
|
||||||
@ -5344,51 +5340,59 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
|
|||||||
* <a href="MethodHandle.html#maxarity">too many parameters</a>
|
* <a href="MethodHandle.html#maxarity">too many parameters</a>
|
||||||
*/
|
*/
|
||||||
public static MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
|
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 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) {
|
boolean nullOnFailure) {
|
||||||
newTypes = copyTypes(newTypes.toArray());
|
Class<?>[] oldTypes = target.type().ptypes();
|
||||||
List<Class<?>> oldTypes = target.type().parameterList();
|
int match = oldTypes.length;
|
||||||
int match = oldTypes.size();
|
|
||||||
if (skip != 0) {
|
if (skip != 0) {
|
||||||
if (skip < 0 || skip > match) {
|
if (skip < 0 || skip > match) {
|
||||||
throw newIllegalArgumentException("illegal skip", skip, target);
|
throw newIllegalArgumentException("illegal skip", skip, target);
|
||||||
}
|
}
|
||||||
oldTypes = oldTypes.subList(skip, match);
|
oldTypes = Arrays.copyOfRange(oldTypes, skip, match);
|
||||||
match -= skip;
|
match -= skip;
|
||||||
}
|
}
|
||||||
List<Class<?>> addTypes = newTypes;
|
Class<?>[] addTypes = newTypes;
|
||||||
int add = addTypes.size();
|
int add = addTypes.length;
|
||||||
if (pos != 0) {
|
if (pos != 0) {
|
||||||
if (pos < 0 || pos > add) {
|
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;
|
add -= pos;
|
||||||
assert(addTypes.size() == add);
|
assert(addTypes.length == add);
|
||||||
}
|
}
|
||||||
// Do not add types which already match the existing arguments.
|
// 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) {
|
if (nullOnFailure) {
|
||||||
return null;
|
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;
|
add -= match;
|
||||||
assert(addTypes.size() == add);
|
assert(addTypes.length == add);
|
||||||
// newTypes: ( P*[pos], M*[match], A*[add] )
|
// newTypes: ( P*[pos], M*[match], A*[add] )
|
||||||
// target: ( S*[skip], M*[match] )
|
// target: ( S*[skip], M*[match] )
|
||||||
MethodHandle adapter = target;
|
MethodHandle adapter = target;
|
||||||
if (add > 0) {
|
if (add > 0) {
|
||||||
adapter = dropArguments0(adapter, skip+ match, addTypes);
|
adapter = dropArgumentsTrusted(adapter, skip+ match, addTypes);
|
||||||
}
|
}
|
||||||
// adapter: (S*[skip], M*[match], A*[add] )
|
// adapter: (S*[skip], M*[match], A*[add] )
|
||||||
if (pos > 0) {
|
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] )
|
// adapter: (S*[skip], P*[pos], M*[match], A*[add] )
|
||||||
return adapter;
|
return adapter;
|
||||||
@ -5452,7 +5456,7 @@ assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
|
|||||||
public static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) {
|
public static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) {
|
||||||
Objects.requireNonNull(target);
|
Objects.requireNonNull(target);
|
||||||
Objects.requireNonNull(newTypes);
|
Objects.requireNonNull(newTypes);
|
||||||
return dropArgumentsToMatch(target, skip, newTypes, pos, false);
|
return dropArgumentsToMatch(target, skip, newTypes.toArray(new Class<?>[0]).clone(), pos, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5771,7 +5775,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
|
|||||||
MethodType targetType = target.type();
|
MethodType targetType = target.type();
|
||||||
MethodType filterType = filter.type();
|
MethodType filterType = filter.type();
|
||||||
Class<?> rtype = filterType.returnType();
|
Class<?> rtype = filterType.returnType();
|
||||||
List<Class<?>> filterArgs = filterType.parameterList();
|
Class<?>[] filterArgs = filterType.ptypes();
|
||||||
if (pos < 0 || (rtype == void.class && pos > targetType.parameterCount()) ||
|
if (pos < 0 || (rtype == void.class && pos > targetType.parameterCount()) ||
|
||||||
(rtype != void.class && pos >= targetType.parameterCount())) {
|
(rtype != void.class && pos >= targetType.parameterCount())) {
|
||||||
throw newIllegalArgumentException("position is out of range for target", target, pos);
|
throw newIllegalArgumentException("position is out of range for target", target, pos);
|
||||||
@ -5782,7 +5786,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
|
|||||||
if (rtype != targetType.parameterType(pos)) {
|
if (rtype != targetType.parameterType(pos)) {
|
||||||
throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6240,8 +6244,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
throw misMatchedTypes("target and fallback types", ttype, ftype);
|
throw misMatchedTypes("target and fallback types", ttype, ftype);
|
||||||
if (gtype.returnType() != boolean.class)
|
if (gtype.returnType() != boolean.class)
|
||||||
throw newIllegalArgumentException("guard type is not a predicate "+gtype);
|
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) {
|
if (test == null) {
|
||||||
throw misMatchedTypes("target and test types", ttype, gtype);
|
throw misMatchedTypes("target and test types", ttype, gtype);
|
||||||
}
|
}
|
||||||
@ -6314,7 +6318,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
throw newIllegalArgumentException("handler does not accept exception type "+exType);
|
throw newIllegalArgumentException("handler does not accept exception type "+exType);
|
||||||
if (htype.returnType() != ttype.returnType())
|
if (htype.returnType() != ttype.returnType())
|
||||||
throw misMatchedTypes("target and handler return types", ttype, htype);
|
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) {
|
if (handler == null) {
|
||||||
throw misMatchedTypes("target and handler types", ttype, htype);
|
throw misMatchedTypes("target and handler types", ttype, htype);
|
||||||
}
|
}
|
||||||
@ -6689,7 +6693,6 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
final List<Class<?>> commonParameterSequence = new ArrayList<>(commonPrefix);
|
final List<Class<?>> commonParameterSequence = new ArrayList<>(commonPrefix);
|
||||||
commonParameterSequence.addAll(commonSuffix);
|
commonParameterSequence.addAll(commonSuffix);
|
||||||
loopChecks2(step, pred, fini, commonParameterSequence);
|
loopChecks2(step, pred, fini, commonParameterSequence);
|
||||||
|
|
||||||
// Step 3: fill in omitted functions.
|
// Step 3: fill in omitted functions.
|
||||||
for (int i = 0; i < nclauses; ++i) {
|
for (int i = 0; i < nclauses; ++i) {
|
||||||
Class<?> t = iterationVariableTypes.get(i);
|
Class<?> t = iterationVariableTypes.get(i);
|
||||||
@ -6700,7 +6703,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
|
step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
|
||||||
}
|
}
|
||||||
if (pred.get(i) == null) {
|
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) {
|
if (fini.get(i) == null) {
|
||||||
fini.set(i, empty(methodType(t, commonParameterSequence)));
|
fini.set(i, empty(methodType(t, commonParameterSequence)));
|
||||||
@ -6799,7 +6802,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
return hs.stream().map(h -> {
|
return hs.stream().map(h -> {
|
||||||
int pc = h.type().parameterCount();
|
int pc = h.type().parameterCount();
|
||||||
int tpsize = targetParams.size();
|
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();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7743,7 +7746,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) {
|
public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) {
|
||||||
List<Class<?>> targetParamTypes = target.type().parameterList();
|
Class<?>[] targetParamTypes = target.type().ptypes();
|
||||||
Class<?> rtype = target.type().returnType();
|
Class<?> rtype = target.type().returnType();
|
||||||
|
|
||||||
tryFinallyChecks(target, cleanup);
|
tryFinallyChecks(target, cleanup);
|
||||||
@ -7751,7 +7754,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
// Match parameter lists: if the cleanup has a shorter parameter list than the target, add ignored arguments.
|
// 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
|
// The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
|
||||||
// target parameter list.
|
// 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
|
// Ensure that the intrinsic type checks the instance thrown by the
|
||||||
// target against the first parameter of cleanup
|
// target against the first parameter of cleanup
|
||||||
|
@ -509,7 +509,7 @@ public final class StringConcatFactory {
|
|||||||
// assembled bottom-up, which makes the code arguably hard to read.
|
// assembled bottom-up, which makes the code arguably hard to read.
|
||||||
|
|
||||||
// Drop all remaining parameter types, leave only helper arguments:
|
// 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
|
// Calculate the initialLengthCoder value by looking at all constant values and summing up
|
||||||
// their lengths and adjusting the encoded coder bit if needed
|
// their lengths and adjusting the encoded coder bit if needed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user