提交 2b94dd73 编写于 作者: J jrose

8019417: JSR 292 javadoc should clarify method handle arity limits

Summary: clarification of erroneous reading of spec. that led to 7194534
Reviewed-by: twisti, darcy
上级 d28f1918
...@@ -392,7 +392,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -392,7 +392,7 @@ mh.invokeExact(System.out, "Hello, world.");
* Java types. * Java types.
* <ul> * <ul>
* <li>Method types range over all possible arities, * <li>Method types range over all possible arities,
* from no arguments to up to 255 of arguments (a limit imposed by the JVM). * from no arguments to up to the <a href="MethodHandle.html#maxarity">maximum number</a> of allowed arguments.
* Generics are not variadic, and so cannot represent this.</li> * Generics are not variadic, and so cannot represent this.</li>
* <li>Method types can specify arguments of primitive types, * <li>Method types can specify arguments of primitive types,
* which Java generic types cannot range over.</li> * which Java generic types cannot range over.</li>
...@@ -402,6 +402,22 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -402,6 +402,22 @@ mh.invokeExact(System.out, "Hello, world.");
* genericity with a Java type parameter.</li> * genericity with a Java type parameter.</li>
* </ul> * </ul>
* *
* <h1><a name="maxarity"></a>Arity limits</h1>
* The JVM imposes on all methods and constructors of any kind an absolute
* limit of 255 stacked arguments. This limit can appear more restrictive
* in certain cases:
* <ul>
* <li>A {@code long} or {@code double} argument counts (for purposes of arity limits) as two argument slots.
* <li>A non-static method consumes an extra argument for the object on which the method is called.
* <li>A constructor consumes an extra argument for the object which is being constructed.
* <li>Since a method handle&rsquo;s {@code invoke} method (or other signature-polymorphic method) is non-virtual,
* it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object.
* </ul>
* These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments.
* For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it.
* Attempts to create method handles with impossible method types lead to an {@link IllegalArgumentException}.
* In particular, a method handle&rsquo;s type must not have an arity of the exact maximum 255.
*
* @see MethodType * @see MethodType
* @see MethodHandles * @see MethodHandles
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
...@@ -831,10 +847,12 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray ...@@ -831,10 +847,12 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray
* @return a new method handle which spreads its final array argument, * @return a new method handle which spreads its final array argument,
* before calling the original method handle * before calling the original method handle
* @throws NullPointerException if {@code arrayType} is a null reference * @throws NullPointerException if {@code arrayType} is a null reference
* @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if {@code arrayType} is not an array type,
* @throws IllegalArgumentException if target does not have at least * or if target does not have at least
* {@code arrayLength} parameter types, * {@code arrayLength} parameter types,
* or if {@code arrayLength} is negative * or if {@code arrayLength} is negative,
* or if the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
* @throws WrongMethodTypeException if the implied {@code asType} call fails * @throws WrongMethodTypeException if the implied {@code asType} call fails
* @see #asCollector * @see #asCollector
*/ */
...@@ -947,7 +965,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); ...@@ -947,7 +965,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123));
* @throws NullPointerException if {@code arrayType} is a null reference * @throws NullPointerException if {@code arrayType} is a null reference
* @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if {@code arrayType} is not an array type
* or {@code arrayType} is not assignable to this method handle's trailing parameter type, * or {@code arrayType} is not assignable to this method handle's trailing parameter type,
* or {@code arrayLength} is not a legal array size * or {@code arrayLength} is not a legal array size,
* or the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
* @throws WrongMethodTypeException if the implied {@code asType} call fails * @throws WrongMethodTypeException if the implied {@code asType} call fails
* @see #asSpreader * @see #asSpreader
* @see #asVarargsCollector * @see #asVarargsCollector
......
...@@ -245,6 +245,10 @@ public class MethodHandles { ...@@ -245,6 +245,10 @@ public class MethodHandles {
* on various grounds (<a href="#secmgr">see below</a>). * on various grounds (<a href="#secmgr">see below</a>).
* By contrast, the {@code ldc} instruction is not subject to * By contrast, the {@code ldc} instruction is not subject to
* security manager checks. * security manager checks.
* <li>If the looked-up method has a
* <a href="MethodHandle.html#maxarity">very large arity</a>,
* the method handle creation may fail, due to the method handle
* type having too many parameters.
* </ul> * </ul>
* *
* <h1><a name="access"></a>Access checking</h1> * <h1><a name="access"></a>Access checking</h1>
...@@ -1522,7 +1526,9 @@ return invoker; ...@@ -1522,7 +1526,9 @@ return invoker;
* @return a method handle suitable for invoking any method handle of the given type * @return a method handle suitable for invoking any method handle of the given type
* @throws NullPointerException if {@code type} is null * @throws NullPointerException if {@code type} is null
* @throws IllegalArgumentException if {@code leadingArgCount} is not in * @throws IllegalArgumentException if {@code leadingArgCount} is not in
* the range from 0 to {@code type.parameterCount()} inclusive * the range from 0 to {@code type.parameterCount()} inclusive,
* or if the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/ */
static public static public
MethodHandle spreadInvoker(MethodType type, int leadingArgCount) { MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
...@@ -1565,6 +1571,8 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1565,6 +1571,8 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
* @param type the desired target type * @param type the desired target type
* @return a method handle suitable for invoking any method handle of the given type * @return a method handle suitable for invoking any method handle of the given type
* @throws IllegalArgumentException if the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/ */
static public static public
MethodHandle exactInvoker(MethodType type) { MethodHandle exactInvoker(MethodType type) {
...@@ -1598,6 +1606,8 @@ publicLookup().findVirtual(MethodHandle.class, "invoke", type) ...@@ -1598,6 +1606,8 @@ publicLookup().findVirtual(MethodHandle.class, "invoke", type)
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
* @param type the desired target type * @param type the desired target type
* @return a method handle suitable for invoking any method handle convertible to the given type * @return a method handle suitable for invoking any method handle convertible to the given type
* @throws IllegalArgumentException if the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/ */
static public static public
MethodHandle invoker(MethodType type) { MethodHandle invoker(MethodType type) {
...@@ -1966,7 +1976,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); ...@@ -1966,7 +1976,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* or if the {@code valueTypes} array or any of its elements is null * or if the {@code valueTypes} array or any of its elements is null
* @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
* or if {@code pos} is negative or greater than the arity of the target, * or if {@code pos} is negative or greater than the arity of the target,
* or if the new method handle's type would have too many parameters * or if the new method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/ */
public static public static
MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) { MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
...@@ -2034,7 +2045,9 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY ...@@ -2034,7 +2045,9 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* or if the {@code filters} array is null * or if the {@code filters} array is null
* @throws IllegalArgumentException if a non-null element of {@code filters} * @throws IllegalArgumentException if a non-null element of {@code filters}
* does not match a corresponding argument type of target as described above, * does not match a corresponding argument type of target as described above,
* or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()} * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
* or if the resulting method handle's type would have
* <a href="MethodHandle.html#maxarity">too many parameters</a>
*/ */
public static public static
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
......
...@@ -92,6 +92,65 @@ public class BigArityTest { ...@@ -92,6 +92,65 @@ public class BigArityTest {
return args; return args;
} }
@Test
public void asCollectorIAE01() throws ReflectiveOperationException {
final int [] INVALID_ARRAY_LENGTHS = {
Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1, 255, 256, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
};
MethodHandle target = MethodHandles.publicLookup().findStatic(Arrays.class,
"deepToString", MethodType.methodType(String.class, Object[].class));
int minbig = Integer.MAX_VALUE;
for (int invalidLength : INVALID_ARRAY_LENGTHS) {
if (minbig > invalidLength && invalidLength > 100) minbig = invalidLength;
try {
target.asCollector(Object[].class, invalidLength);
assert(false) : invalidLength;
} catch (IllegalArgumentException ex) {
System.out.println("OK: "+ex);
}
}
// Sizes not in the above array are good:
target.asCollector(Object[].class, minbig-1);
for (int i = 2; i <= 10; i++)
target.asCollector(Object[].class, minbig-i);
}
@Test
public void invoker02() {
for (int i = 0; i < 255; i++) {
MethodType mt = MethodType.genericMethodType(i);
MethodType expMT = mt.insertParameterTypes(0, MethodHandle.class);
if (i < 254) {
assertEquals(expMT, MethodHandles.invoker(mt).type());
} else {
try {
MethodHandles.invoker(mt);
assert(false) : i;
} catch (IllegalArgumentException ex) {
System.out.println("OK: "+ex);
}
}
}
}
@Test
public void exactInvoker02() {
for (int i = 0; i < 255; i++) {
MethodType mt = MethodType.genericMethodType(i);
MethodType expMT = mt.insertParameterTypes(0, MethodHandle.class);
if (i < 254) {
assertEquals(expMT, MethodHandles.exactInvoker(mt).type());
} else {
try {
MethodHandles.exactInvoker(mt);
assert(false) : i;
} catch (IllegalArgumentException ex) {
System.out.println("OK: "+ex);
}
}
}
}
@Test @Test
public void testBoundaryValues() throws Throwable { public void testBoundaryValues() throws Throwable {
for (int badArity : new int[]{ -1, MAX_JVM_ARITY+1, MAX_JVM_ARITY }) { for (int badArity : new int[]{ -1, MAX_JVM_ARITY+1, MAX_JVM_ARITY }) {
...@@ -102,6 +161,37 @@ public class BigArityTest { ...@@ -102,6 +161,37 @@ public class BigArityTest {
System.out.println("OK: "+ex); System.out.println("OK: "+ex);
} }
} }
final int MAX_MH_ARITY = MAX_JVM_ARITY - 1; // mh.invoke(arg*[N])
final int MAX_INVOKER_ARITY = MAX_MH_ARITY - 1; // inv.invoke(mh, arg*[N])
for (int arity : new int[]{ 0, 1, MAX_MH_ARITY-2, MAX_MH_ARITY-1, MAX_MH_ARITY }) {
MethodHandle mh = MH_hashArguments(arity);
if (arity < MAX_INVOKER_ARITY) {
MethodHandle ximh = MethodHandles.exactInvoker(mh.type());
MethodHandle gimh = MethodHandles.invoker(mh.type());
MethodHandle simh = MethodHandles.spreadInvoker(mh.type(), 0);
if (arity != 0) {
simh = MethodHandles.spreadInvoker(mh.type(), 1);
} else {
try {
simh = MethodHandles.spreadInvoker(mh.type(), 1);
assert(false) : arity;
} catch (IllegalArgumentException ex) {
System.out.println("OK: "+ex);
}
}
if (arity != 0) {
simh = MethodHandles.spreadInvoker(mh.type(), arity-1);
} else {
try {
simh = MethodHandles.spreadInvoker(mh.type(), arity-1);
assert(false) : arity;
} catch (IllegalArgumentException ex) {
System.out.println("OK: "+ex);
}
}
simh = MethodHandles.spreadInvoker(mh.type(), arity);
}
}
} }
// Make sure the basic argument spreading and varargs mechanisms are working. // Make sure the basic argument spreading and varargs mechanisms are working.
...@@ -133,7 +223,7 @@ public class BigArityTest { ...@@ -133,7 +223,7 @@ public class BigArityTest {
if (cls == Object[].class) if (cls == Object[].class)
r = smh.invokeExact(tail); r = smh.invokeExact(tail);
else if (cls == Integer[].class) else if (cls == Integer[].class)
r = smh.invokeExact((Integer[]) tail); r = smh.invokeExact((Integer[]) tail); //warning OK, see 8019340
else else
r = smh.invoke(tail); r = smh.invoke(tail);
assertEquals(r0, r); assertEquals(r0, r);
...@@ -235,21 +325,41 @@ public class BigArityTest { ...@@ -235,21 +325,41 @@ public class BigArityTest {
MethodHandle mh_VA = mh.asSpreader(cls, arity); MethodHandle mh_VA = mh.asSpreader(cls, arity);
assert(mh_VA.type().parameterType(0) == cls); assert(mh_VA.type().parameterType(0) == cls);
testArities(cls, arity, iterations, verbose, mh, mh_VA); testArities(cls, arity, iterations, verbose, mh, mh_VA);
// mh_CA will collect arguments of a particular type and pass them to mh_VA
MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
assert(mh_CA.type().equals(mh.type()));
assert(mh_VA2.type().equals(mh_VA.type()));
if (cls != Object[].class) { if (cls != Object[].class) {
// mh_CA will collect arguments of a particular type and pass them to mh_VA
MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
try { try {
mh_VA2.invokeWithArguments(new Object[arity]); mh_VA2.invokeWithArguments(new Object[arity]);
throw new AssertionError("should not reach"); throw new AssertionError("should not reach");
} catch (ClassCastException | WrongMethodTypeException ex) { } catch (ClassCastException | WrongMethodTypeException ex) {
} }
assert(mh_CA.type().equals(mh.type()));
assert(mh_VA2.type().equals(mh_VA.type()));
testArities(cls, arity, iterations, false, mh_CA, mh_VA2);
} }
int iterations_VA = iterations / 100;
testArities(cls, arity, iterations_VA, false, mh_CA, mh_VA2);
} }
} }
/**
* Tests calls to {@link BigArityTest#hashArguments hashArguments} as related to a single given arity N.
* Applies the given {@code mh} to a set of N integer arguments, checking the answer.
* Also applies the varargs variation {@code mh_VA} to an array of type C[] (given by {@code cls}).
* Test steps:
* <ul>
* <li>mh_VA.invokeExact(new C[]{ arg, ... })</li>
* <li>mh.invokeWithArguments((Object[]) new C[]{ arg, ... })</li>
* <li>exactInvoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
* <li>invoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
* </ul>
* @param cls array type for varargs call (one of Object[], Number[], Integer[], Comparable[])
* @param arity N, the number of arguments to {@code mh} and length of its varargs array, in [0..255]
* @param iterations number of times to repeat each test step (at least 4)
* @param verbose are we printing extra output?
* @param mh a fixed-arity version of {@code hashArguments}
* @param mh_VA a variable-arity version of {@code hashArguments}, accepting the given array type {@code cls}
*/
private void testArities(Class<? extends Object[]> cls, private void testArities(Class<? extends Object[]> cls,
int arity, int arity,
int iterations, int iterations,
...@@ -292,7 +402,7 @@ public class BigArityTest { ...@@ -292,7 +402,7 @@ public class BigArityTest {
if (cls == Object[].class) if (cls == Object[].class)
r = mh_VA.invokeExact(args); r = mh_VA.invokeExact(args);
else if (cls == Integer[].class) else if (cls == Integer[].class)
r = mh_VA.invokeExact((Integer[])args); r = mh_VA.invokeExact((Integer[])args); //warning OK, see 8019340
else else
r = mh_VA.invoke(args); r = mh_VA.invoke(args);
assertEquals(r0, r); assertEquals(r0, r);
...@@ -392,10 +502,16 @@ public class BigArityTest { ...@@ -392,10 +502,16 @@ public class BigArityTest {
a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB]); a[0xF8], a[0xF9], a[0xFA], a[0xFB]); // hashArguments_252
assertEquals(r0, r); assertEquals(r0, r);
MethodType mt = MethodType.genericMethodType(ARITY); MethodType mt = MethodType.genericMethodType(ARITY);
MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
test252(mh, a, r0);
MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
test252(mh_CA, a, r0);
}
public void test252(MethodHandle mh, Object[] a, Object r0) throws Throwable {
Object r;
r = mh.invokeExact( r = mh.invokeExact(
// <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
...@@ -599,10 +715,16 @@ public class BigArityTest { ...@@ -599,10 +715,16 @@ public class BigArityTest {
a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); // hashArguments_253
assertEquals(r0, r); assertEquals(r0, r);
MethodType mt = MethodType.genericMethodType(ARITY); MethodType mt = MethodType.genericMethodType(ARITY);
MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
test253(mh, a, r0);
MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
test253(mh_CA, a, r0);
}
public void test253(MethodHandle mh, Object[] a, Object r0) throws Throwable {
Object r;
r = mh.invokeExact( r = mh.invokeExact(
// <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
...@@ -648,7 +770,6 @@ public class BigArityTest { ...@@ -648,7 +770,6 @@ public class BigArityTest {
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
assertEquals(r0, r); assertEquals(r0, r);
// FIXME: This next one fails, because it uses an internal invoker of arity 255.
r = ximh.invokeWithArguments(cat(mh,a)); r = ximh.invokeWithArguments(cat(mh,a));
assertEquals(r0, r); assertEquals(r0, r);
MethodHandle gimh = MethodHandles.invoker(mh.type()); MethodHandle gimh = MethodHandles.invoker(mh.type());
...@@ -674,7 +795,6 @@ public class BigArityTest { ...@@ -674,7 +795,6 @@ public class BigArityTest {
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
assertEquals(r0, r); assertEquals(r0, r);
// FIXME: This next one fails, because it uses an internal invoker of arity 255.
r = gimh.invokeWithArguments(cat(mh,a)); r = gimh.invokeWithArguments(cat(mh,a));
assertEquals(r0, r); assertEquals(r0, r);
mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class));
...@@ -808,10 +928,16 @@ public class BigArityTest { ...@@ -808,10 +928,16 @@ public class BigArityTest {
a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); // hashArguments_254
assertEquals(r0, r); assertEquals(r0, r);
MethodType mt = MethodType.genericMethodType(ARITY); MethodType mt = MethodType.genericMethodType(ARITY);
MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
test254(mh, a, r0);
MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
test254(mh_CA, a, r0);
}
public void test254(MethodHandle mh, Object[] a, Object r0) throws Throwable {
Object r;
r = mh.invokeExact( r = mh.invokeExact(
// <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
...@@ -833,7 +959,6 @@ public class BigArityTest { ...@@ -833,7 +959,6 @@ public class BigArityTest {
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]);
assertEquals(r0, r); assertEquals(r0, r);
// FIXME: This next one fails, because it uses an internal invoker of arity 255.
r = mh.invokeWithArguments(a); r = mh.invokeWithArguments(a);
assertEquals(r0, r); assertEquals(r0, r);
try { try {
...@@ -998,7 +1123,7 @@ public class BigArityTest { ...@@ -998,7 +1123,7 @@ public class BigArityTest {
a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
// </editor-fold> // </editor-fold>
a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); // hashArguments_255
assertEquals(r0, r); assertEquals(r0, r);
MethodType mt = MethodType.genericMethodType(ARITY); MethodType mt = MethodType.genericMethodType(ARITY);
MethodHandle mh; MethodHandle mh;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册