7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
Implement invocation corner cases, including correct type conversions and interface type enforcement. Reviewed-by: never
This commit is contained in:
parent
9a58e303d7
commit
4b011923e2
@ -141,7 +141,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
while (lastConv >= 0) {
|
||||
Class<?> src = newType.parameterType(lastConv); // source type
|
||||
Class<?> dst = oldType.parameterType(lastConv); // destination type
|
||||
if (VerifyType.isNullConversion(src, dst)) {
|
||||
if (isTrivialConversion(src, dst, level)) {
|
||||
--lastConv;
|
||||
} else {
|
||||
break;
|
||||
@ -150,7 +150,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
|
||||
Class<?> needReturn = newType.returnType();
|
||||
Class<?> haveReturn = oldType.returnType();
|
||||
boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn);
|
||||
boolean retConv = !isTrivialConversion(haveReturn, needReturn, level);
|
||||
|
||||
// Now build a chain of one or more adapters.
|
||||
MethodHandle adapter = target, adapter2;
|
||||
@ -158,7 +158,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
for (int i = 0; i <= lastConv; i++) {
|
||||
Class<?> src = newType.parameterType(i); // source type
|
||||
Class<?> dst = midType.parameterType(i); // destination type
|
||||
if (VerifyType.isNullConversion(src, dst)) {
|
||||
if (isTrivialConversion(src, dst, level)) {
|
||||
// do nothing: difference is trivial
|
||||
continue;
|
||||
}
|
||||
@ -219,6 +219,22 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private static boolean isTrivialConversion(Class<?> src, Class<?> dst, int level) {
|
||||
if (src == dst || dst == void.class) return true;
|
||||
if (!VerifyType.isNullConversion(src, dst)) return false;
|
||||
if (level > 1) return true; // explicitCastArguments
|
||||
boolean sp = src.isPrimitive();
|
||||
boolean dp = dst.isPrimitive();
|
||||
if (sp != dp) return false;
|
||||
if (sp) {
|
||||
// in addition to being a null conversion, forbid boolean->int etc.
|
||||
return Wrapper.forPrimitiveType(dst)
|
||||
.isConvertibleFrom(Wrapper.forPrimitiveType(src));
|
||||
} else {
|
||||
return dst.isAssignableFrom(src);
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) {
|
||||
MethodHandle adjustReturn;
|
||||
if (haveReturn == void.class) {
|
||||
@ -596,7 +612,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
|| !VerifyType.isNullConversion(castType, dst))
|
||||
return false;
|
||||
int diff = diffTypes(newType, targetType, false);
|
||||
return (diff == arg+1); // arg is sole non-trivial diff
|
||||
return (diff == arg+1) || (diff == 0); // arg is sole non-trivial diff
|
||||
}
|
||||
/** Can an primitive conversion adapter validly convert src to dst? */
|
||||
static boolean canCheckCast(Class<?> src, Class<?> dst) {
|
||||
@ -1033,8 +1049,9 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
|
||||
// FIXME: Get rid of newType; derive new arguments from structure of spreadArgType
|
||||
MethodType targetType = target.type();
|
||||
if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
|
||||
return null;
|
||||
assert(canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
|
||||
: "[newType, targetType, spreadArgType, spreadArgPos, spreadArgCount] = "
|
||||
+ Arrays.asList(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount);
|
||||
// dest is not significant; remove?
|
||||
int dest = T_VOID;
|
||||
for (int i = 0; i < spreadArgCount; i++) {
|
||||
|
@ -129,20 +129,17 @@ class InvokeGeneric {
|
||||
if (needType == erasedCallerType.returnType())
|
||||
return false; // no conversions possible, since must be primitive or Object
|
||||
Class<?> haveType = target.type().returnType();
|
||||
if (VerifyType.isNullConversion(haveType, needType))
|
||||
if (VerifyType.isNullConversion(haveType, needType) && !needType.isInterface())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
|
||||
if (true) throw new RuntimeException("NYI");
|
||||
private MethodHandle addReturnConversion(MethodHandle finisher, Class<?> type) {
|
||||
// FIXME: This is slow because it creates a closure node on every call that requires a return cast.
|
||||
MethodType targetType = target.type();
|
||||
MethodType finisherType = finisher.type();
|
||||
MethodHandle caster = ValueConversions.identity(type);
|
||||
caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
|
||||
// Drop irrelevant arguments, because we only care about the return value:
|
||||
caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
|
||||
MethodHandle result = MethodHandles.foldArguments(caster, target);
|
||||
return result.asType(target.type());
|
||||
caster = caster.asType(caster.type().changeParameterType(0, finisherType.returnType()));
|
||||
finisher = MethodHandles.filterReturnValue(finisher, caster);
|
||||
return finisher.asType(finisherType);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -708,9 +708,9 @@ public abstract class MethodHandle {
|
||||
*/
|
||||
public MethodHandle asType(MethodType newType) {
|
||||
if (!type.isConvertibleTo(newType)) {
|
||||
throw new WrongMethodTypeException("cannot convert "+type+" to "+newType);
|
||||
throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
|
||||
}
|
||||
return MethodHandles.convertArguments(this, newType);
|
||||
return MethodHandleImpl.convertArguments(this, newType, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,9 +93,28 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
static
|
||||
MethodHandle makeAllocator(MethodHandle rawConstructor) {
|
||||
MethodType rawConType = rawConstructor.type();
|
||||
Class<?> allocateClass = rawConType.parameterType(0);
|
||||
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
|
||||
if (AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)) {
|
||||
// allocator(arg...)
|
||||
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
|
||||
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
|
||||
MethodHandle returner = MethodHandles.identity(allocateClass);
|
||||
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
|
||||
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
|
||||
return fold;
|
||||
}
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodHandle allocator
|
||||
= AllocateObject.make(rawConType.parameterType(0), rawConstructor);
|
||||
= AllocateObject.make(allocateClass, rawConstructor);
|
||||
assert(allocator.type()
|
||||
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
|
||||
return allocator;
|
||||
@ -112,8 +131,16 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
super(invoker);
|
||||
this.allocateClass = allocateClass;
|
||||
this.rawConstructor = rawConstructor;
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
}
|
||||
// for allocation only:
|
||||
private AllocateObject(Class<C> allocateClass) {
|
||||
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
|
||||
this.allocateClass = allocateClass;
|
||||
this.rawConstructor = null;
|
||||
}
|
||||
static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodType rawConType = rawConstructor.type();
|
||||
assert(rawConType.parameterType(0) == allocateClass);
|
||||
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
|
||||
@ -129,7 +156,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
} else {
|
||||
MethodHandle invoke = VARARGS_INVOKE;
|
||||
MethodType conType = CON_TYPES[nargs];
|
||||
MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
|
||||
MethodHandle gcon = spreadArgumentsFromPos(rawConstructor, conType, 1);
|
||||
if (gcon == null) return null;
|
||||
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
|
||||
return collectArguments(galloc, newType, 1, null);
|
||||
@ -214,9 +241,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
// For testing use this:
|
||||
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
|
||||
static final MethodHandle VARARGS_INVOKE;
|
||||
static final MethodHandle ALLOCATE;
|
||||
static {
|
||||
try {
|
||||
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
|
||||
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw uncaughtException(ex);
|
||||
}
|
||||
@ -747,7 +776,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
.insertParameterTypes(keepPosArgs, arrayType);
|
||||
return spreadArguments(target, newType, keepPosArgs, arrayType, arrayLength);
|
||||
}
|
||||
static MethodHandle spreadArguments(MethodHandle target, MethodType newType, int spreadArgPos) {
|
||||
static MethodHandle spreadArgumentsFromPos(MethodHandle target, MethodType newType, int spreadArgPos) {
|
||||
int arrayLength = target.type().parameterCount() - spreadArgPos;
|
||||
return spreadArguments(target, newType, spreadArgPos, Object[].class, arrayLength);
|
||||
}
|
||||
@ -761,9 +790,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
// spread the last argument of newType to oldType
|
||||
assert(arrayLength == oldType.parameterCount() - spreadArgPos);
|
||||
assert(newType.parameterType(spreadArgPos) == arrayType);
|
||||
MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength);
|
||||
if (res == null) throw new IllegalArgumentException("spread on "+target+" with "+arrayType.getSimpleName());
|
||||
return res;
|
||||
return AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength);
|
||||
}
|
||||
|
||||
static MethodHandle collectArguments(MethodHandle target,
|
||||
@ -771,6 +798,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodHandle collector) {
|
||||
MethodType type = target.type();
|
||||
Class<?> collectType = collector.type().returnType();
|
||||
assert(collectType != void.class); // else use foldArguments
|
||||
if (collectType != type.parameterType(collectArg))
|
||||
target = target.asType(type.changeParameterType(collectArg, collectType));
|
||||
MethodType newType = type
|
||||
@ -878,9 +906,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
this.test = test;
|
||||
this.target = target;
|
||||
this.fallback = fallback;
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
}
|
||||
// FIXME: Build the control flow out of foldArguments.
|
||||
static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
MethodType type = target.type();
|
||||
int nargs = type.parameterCount();
|
||||
if (nargs < INVOKES.length) {
|
||||
@ -897,9 +927,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodHandle invoke = VARARGS_INVOKE;
|
||||
MethodType gtype = MethodType.genericMethodType(1);
|
||||
assert(invoke.type().dropParameterTypes(0,1) == gtype);
|
||||
MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0);
|
||||
MethodHandle gtarget = spreadArguments(target, gtype, 0);
|
||||
MethodHandle gfallback = spreadArguments(fallback, gtype, 0);
|
||||
MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
|
||||
MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
|
||||
MethodHandle gfallback = spreadArgumentsFromPos(fallback, gtype, 0);
|
||||
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
|
||||
if (gtest == null || gtarget == null || gfallback == null) return null;
|
||||
return collectArguments(gguard, type, 0, null);
|
||||
@ -989,10 +1019,49 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
|
||||
return testResult ? target : fallback;
|
||||
}
|
||||
|
||||
static MethodHandle SELECT_ALTERNATIVE;
|
||||
static MethodHandle selectAlternative() {
|
||||
if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE;
|
||||
try {
|
||||
SELECT_ALTERNATIVE
|
||||
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
|
||||
MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return SELECT_ALTERNATIVE;
|
||||
}
|
||||
|
||||
static
|
||||
MethodHandle makeGuardWithTest(MethodHandle test,
|
||||
MethodHandle target,
|
||||
MethodHandle fallback) {
|
||||
// gwt(arg...)
|
||||
// [fold]=> continueAfterTest(z=test(arg...), arg...)
|
||||
// [filter]=> (tf=select(z))(arg...)
|
||||
// where select(z) = select(z, t, f).bindTo(t, f) => z ? t f
|
||||
// [tailcall]=> tf(arg...)
|
||||
assert(test.type().returnType() == boolean.class);
|
||||
MethodType foldTargetType = target.type().insertParameterTypes(0, boolean.class);
|
||||
if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)) {
|
||||
// working backwards, as usual:
|
||||
assert(target.type().equals(fallback.type()));
|
||||
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
|
||||
MethodHandle select = selectAlternative();
|
||||
select = bindArgument(select, 2, fallback);
|
||||
select = bindArgument(select, 1, target);
|
||||
// select(z: boolean) => (z ? target : fallback)
|
||||
MethodHandle filter = filterArgument(tailcall, 0, select);
|
||||
assert(filter.type().parameterType(0) == boolean.class);
|
||||
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
|
||||
return fold;
|
||||
}
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
return GuardWithTest.make(test, target, fallback);
|
||||
}
|
||||
|
||||
@ -1144,11 +1213,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
} else {
|
||||
MethodType gtype = MethodType.genericMethodType(0, true);
|
||||
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
|
||||
MethodHandle gtarget = spreadArguments(target, gtype, 0);
|
||||
MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1);
|
||||
MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
|
||||
catcher = catcher.asType(ctype.changeParameterType(0, Throwable.class));
|
||||
MethodHandle gcatcher = spreadArgumentsFromPos(catcher, gcatchType, 1);
|
||||
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
|
||||
if (gtarget == null || gcatcher == null || gguard == null) return null;
|
||||
return collectArguments(gguard, type, 0, null);
|
||||
return collectArguments(gguard, type, 0, ValueConversions.varargsArray(nargs)).asType(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1377,6 +1377,9 @@ publicLookup().findVirtual(MethodHandle.class, "invoke", type)
|
||||
*/
|
||||
public static
|
||||
MethodHandle convertArguments(MethodHandle target, MethodType newType) {
|
||||
if (!target.type().isConvertibleTo(newType)) {
|
||||
throw new WrongMethodTypeException("cannot convert "+target+" to "+newType);
|
||||
}
|
||||
return MethodHandleImpl.convertArguments(target, newType, 1);
|
||||
}
|
||||
|
||||
@ -1567,7 +1570,7 @@ assert((int)twice.invokeExact(21) == 42);
|
||||
int numSpread = (outargs - spreadPos);
|
||||
MethodHandle res = null;
|
||||
if (spreadPos >= 0 && numSpread >= 0) {
|
||||
res = MethodHandleImpl.spreadArguments(target, newType, spreadPos);
|
||||
res = MethodHandleImpl.spreadArgumentsFromPos(target, newType, spreadPos);
|
||||
}
|
||||
if (res == null) {
|
||||
throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
|
||||
@ -2135,7 +2138,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
|
||||
int hpc = hargs.size(), tpc = targs.size();
|
||||
if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
|
||||
throw misMatchedTypes("target and handler types", ttype, htype);
|
||||
handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
|
||||
handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc));
|
||||
htype = handler.type();
|
||||
}
|
||||
return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
|
||||
|
@ -258,7 +258,7 @@ public enum Wrapper {
|
||||
}
|
||||
|
||||
/** Return the wrapper that wraps values into the given wrapper type.
|
||||
* If it is {@code Object} or an interface, return {@code OBJECT}.
|
||||
* If it is {@code Object}, return {@code OBJECT}.
|
||||
* Otherwise, it must be a wrapper type.
|
||||
* The type must not be a primitive type.
|
||||
* @throws IllegalArgumentException for unexpected types
|
||||
@ -277,8 +277,6 @@ public enum Wrapper {
|
||||
if (w != null && w.wrapperType == type) {
|
||||
return w;
|
||||
}
|
||||
if (type.isInterface())
|
||||
return OBJECT;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -51,10 +51,10 @@ public class Test6991596 {
|
||||
return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
|
||||
}
|
||||
static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
|
||||
return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
|
||||
return MethodHandles.explicitCastArguments(mh1, MethodType.methodType(ret, arg));
|
||||
}
|
||||
static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
|
||||
return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
|
||||
return MethodHandles.explicitCastArguments(mh1, MethodType.methodType(ret, arg));
|
||||
}
|
||||
|
||||
// test adapter_opt_i2i
|
||||
|
@ -53,9 +53,9 @@ public class InvokeGenericTest {
|
||||
if (vstr != null) verbosity = Integer.parseInt(vstr);
|
||||
}
|
||||
|
||||
public static void main(String... av) throws Throwable {
|
||||
new InvokeGenericTest().testFirst();
|
||||
}
|
||||
// public static void main(String... av) throws Throwable {
|
||||
// new InvokeGenericTest().testFirst();
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testFirst() throws Throwable {
|
||||
@ -470,8 +470,6 @@ public class InvokeGenericTest {
|
||||
return allMethodTypes(argc, argc, types);
|
||||
}
|
||||
|
||||
interface RandomInterface { }
|
||||
|
||||
MethodHandle toString_MH;
|
||||
|
||||
@Test
|
||||
@ -480,33 +478,62 @@ public class InvokeGenericTest {
|
||||
toString_MH = LOOKUP.
|
||||
findVirtual(Object.class, "toString", MethodType.methodType(String.class));
|
||||
Object[] args = { "one", "two" };
|
||||
for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
|
||||
for (MethodType type : allMethodTypes(2, Object.class, String.class, CharSequence.class)) {
|
||||
testReferenceConversions(type, args);
|
||||
}
|
||||
}
|
||||
public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
|
||||
countTest();
|
||||
if (verbosity > 3) System.out.println("target type: "+type);
|
||||
int nargs = args.length;
|
||||
List<Object> argList = Arrays.asList(args);
|
||||
String expectString = argList.toString();
|
||||
if (verbosity > 3) System.out.println("target type: "+type+expectString);
|
||||
MethodHandle mh = callable(type.parameterList());
|
||||
MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
|
||||
mh = MethodHandles.foldArguments(tsdrop, mh);
|
||||
mh = MethodHandles.filterReturnValue(mh, toString_MH);
|
||||
mh = mh.asType(type);
|
||||
Object res = mh.invoke((String)args[0], (Object)args[1]);
|
||||
Object res = null;
|
||||
if (nargs == 2) {
|
||||
res = mh.invoke((Object)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = mh.invoke((String)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = mh.invoke((Object)args[0], (String)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = mh.invoke((String)args[0], (String)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = mh.invoke((String)args[0], (CharSequence)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = mh.invoke((CharSequence)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = (String) mh.invoke((Object)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = (String) mh.invoke((String)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
res = (CharSequence) mh.invoke((String)args[0], (Object)args[1]);
|
||||
assertEquals(expectString, res);
|
||||
} else {
|
||||
assert(false); // write this code
|
||||
}
|
||||
//System.out.println(res);
|
||||
assertEquals(Arrays.asList(args).toString(), res);
|
||||
}
|
||||
|
||||
|
||||
@Test @Ignore("known failure pending 6939861")
|
||||
@Test
|
||||
public void testBoxConversions() throws Throwable {
|
||||
startTest("testBoxConversions");
|
||||
countTest();
|
||||
Object[] args = { 1, 2 };
|
||||
MethodHandle mh = callable(Object.class, int.class);
|
||||
Object res; List resl;
|
||||
Object res; List resl; int resi;
|
||||
res = resl = (List) mh.invoke((int)args[0], (Object)args[1]);
|
||||
//System.out.println(res);
|
||||
assertEquals(Arrays.asList(args), res);
|
||||
mh = MethodHandles.identity(int.class);
|
||||
mh = MethodHandles.dropArguments(mh, 1, int.class);
|
||||
res = resi = (int) mh.invoke((Object) args[0], (Object) args[1]);
|
||||
assertEquals(args[0], res);
|
||||
res = resi = (int) mh.invoke((int) args[0], (Object) args[1]);
|
||||
assertEquals(args[0], res);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user