提交 ff2cda9e 编写于 作者: V vlivanov

8057654: Extract checks performed during MethodHandle construction into separate methods

Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
上级 f7ec9348
......@@ -869,29 +869,34 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray
return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
}
private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
/**
* See if {@code asSpreader} can be validly called with the given arguments.
* Return the type of the method handle call after spreading but before conversions.
*/
private MethodType asSpreaderChecks(Class<?> arrayType, int arrayLength) {
spreadArrayChecks(arrayType, arrayLength);
int nargs = type().parameterCount();
if (nargs < arrayLength || arrayLength < 0)
throw newIllegalArgumentException("bad spread array length");
if (arrayType != Object[].class && arrayLength != 0) {
boolean sawProblem = false;
Class<?> arrayElement = arrayType.getComponentType();
for (int i = nargs - arrayLength; i < nargs; i++) {
if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
sawProblem = true;
Class<?> arrayElement = arrayType.getComponentType();
MethodType mtype = type();
boolean match = true, fail = false;
for (int i = nargs - arrayLength; i < nargs; i++) {
Class<?> ptype = mtype.parameterType(i);
if (ptype != arrayElement) {
match = false;
if (!MethodType.canConvert(arrayElement, ptype)) {
fail = true;
break;
}
}
if (sawProblem) {
ArrayList<Class<?>> ptypes = new ArrayList<>(type().parameterList());
for (int i = nargs - arrayLength; i < nargs; i++) {
ptypes.set(i, arrayElement);
}
// elicit an error:
this.asType(MethodType.methodType(type().returnType(), ptypes));
}
}
if (match) return mtype;
MethodType needType = mtype.asSpreaderType(arrayType, arrayLength);
if (!fail) return needType;
// elicit an error:
this.asType(needType);
throw newInternalError("should not return", null);
}
private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
......
......@@ -2509,32 +2509,36 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
*/
public static
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
MethodType targetType = target.type();
filterArgumentsCheckArity(target, pos, filters);
MethodHandle adapter = target;
MethodType adapterType = null;
assert((adapterType = targetType) != null);
int maxPos = targetType.parameterCount();
if (pos + filters.length > maxPos)
throw newIllegalArgumentException("too many filters");
int curPos = pos-1; // pre-incremented
for (MethodHandle filter : filters) {
curPos += 1;
if (filter == null) continue; // ignore null elements of filters
adapter = filterArgument(adapter, curPos, filter);
assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
}
assert(adapterType.equals(adapter.type()));
return adapter;
}
/*non-public*/ static
MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
filterArgumentChecks(target, pos, filter);
return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
}
private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
MethodType targetType = target.type();
int maxPos = targetType.parameterCount();
if (pos + filters.length > maxPos)
throw newIllegalArgumentException("too many filters");
}
private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
MethodType targetType = target.type();
MethodType filterType = filter.type();
if (filterType.parameterCount() != 1
|| filterType.returnType() != targetType.parameterType(pos))
throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
}
/**
......@@ -2714,15 +2718,17 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
MethodType targetType = target.type();
MethodType filterType = filter.type();
filterReturnValueChecks(targetType, filterType);
return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
}
private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException {
Class<?> rtype = targetType.returnType();
int filterValues = filterType.parameterCount();
if (filterValues == 0
? (rtype != void.class)
: (rtype != filterType.parameterType(0)))
throw newIllegalArgumentException("target and filter types do not match", target, filter);
// result = fold( lambda(retval, arg...) { filter(retval) },
// lambda( arg...) { target(arg...) } )
return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
}
/**
......@@ -2803,24 +2809,28 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
*/
public static
MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
int pos = 0;
int foldPos = 0;
MethodType targetType = target.type();
MethodType combinerType = combiner.type();
int foldPos = pos;
int foldArgs = combinerType.parameterCount();
int foldVals = combinerType.returnType() == void.class ? 0 : 1;
Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
}
private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
int foldArgs = combinerType.parameterCount();
Class<?> rtype = combinerType.returnType();
int foldVals = rtype == void.class ? 0 : 1;
int afterInsertPos = foldPos + foldVals;
boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
if (ok && !(combinerType.parameterList()
.equals(targetType.parameterList().subList(afterInsertPos,
afterInsertPos + foldArgs))))
ok = false;
if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
ok = false;
if (!ok)
throw misMatchedTypes("target and combiner types", targetType, combinerType);
MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
return rtype;
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册