mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8152667: MHs.iteratedLoop(...) throws unexpected WMTE, disallows Iterator subclasses, generates inconsistent loop result type
Reviewed-by: redestad
This commit is contained in:
parent
741bd9b060
commit
5b392c0abc
2 changed files with 94 additions and 10 deletions
|
@ -4572,17 +4572,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
||||||
*/
|
*/
|
||||||
public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
|
public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
|
||||||
checkIteratedLoop(iterator, body);
|
checkIteratedLoop(iterator, body);
|
||||||
final boolean voidInit = init == null || init.type().returnType() == void.class;
|
Class<?> resultType = init == null ?
|
||||||
|
body == null ? void.class : body.type().returnType() :
|
||||||
|
init.type().returnType();
|
||||||
|
boolean voidResult = resultType == void.class;
|
||||||
|
|
||||||
|
MethodHandle initIterator;
|
||||||
|
if (iterator == null) {
|
||||||
|
MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
|
||||||
|
initIterator = initit.asType(initit.type().changeParameterType(0,
|
||||||
|
body.type().parameterType(voidResult ? 1 : 2)));
|
||||||
|
} else {
|
||||||
|
initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class));
|
||||||
|
}
|
||||||
|
|
||||||
MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
|
|
||||||
MethodHandle initIterator = iterator == null ?
|
|
||||||
initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) :
|
|
||||||
iterator;
|
|
||||||
Class<?> itype = initIterator.type().returnType();
|
|
||||||
Class<?> ttype = body.type().parameterType(0);
|
Class<?> ttype = body.type().parameterType(0);
|
||||||
|
|
||||||
MethodHandle returnVar =
|
MethodHandle returnVar =
|
||||||
dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype);
|
dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class);
|
||||||
MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
|
MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
|
||||||
MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
|
MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* @bug 8150635
|
* @bug 8150635
|
||||||
* @bug 8150956
|
* @bug 8150956
|
||||||
* @bug 8150957
|
* @bug 8150957
|
||||||
|
* @bug 8152667
|
||||||
* @bug 8153637
|
* @bug 8153637
|
||||||
* @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
|
* @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
|
||||||
*/
|
*/
|
||||||
|
@ -400,10 +401,15 @@ public class LoopCombinatorTest {
|
||||||
assertTrue(caught);
|
assertTrue(caught);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@DataProvider
|
||||||
public static void testIterateVoidIterator() {
|
static Object[][] wrongIteratorTypes() {
|
||||||
|
return new Object[][]{{void.class}, {Object.class}, {Iterable.class}};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "wrongIteratorTypes")
|
||||||
|
public static void testIterateVoidIterator(Class<?> it) {
|
||||||
boolean caught = false;
|
boolean caught = false;
|
||||||
MethodType v = methodType(void.class);
|
MethodType v = methodType(it);
|
||||||
try {
|
try {
|
||||||
MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v));
|
MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v));
|
||||||
} catch(IllegalArgumentException iae) {
|
} catch(IllegalArgumentException iae) {
|
||||||
|
@ -420,6 +426,77 @@ public class LoopCombinatorTest {
|
||||||
loop.invoke(Arrays.asList("hello", "world"));
|
loop.invoke(Arrays.asList("hello", "world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
static Object[][] iterateParameters() {
|
||||||
|
MethodType i = methodType(int.class);
|
||||||
|
MethodType sil_i = methodType(int.class, String.class, int.class, List.class);
|
||||||
|
MethodType sl_v = methodType(void.class, String.class, List.class);
|
||||||
|
MethodType l_it = methodType(Iterator.class, List.class);
|
||||||
|
MethodType li_it = methodType(Iterator.class, List.class, int.class);
|
||||||
|
MethodType l_i = methodType(int.class, List.class);
|
||||||
|
MethodType _it = methodType(Iterator.class);
|
||||||
|
MethodType si_i = methodType(int.class, String.class, int.class);
|
||||||
|
MethodType s_i = methodType(int.class, String.class);
|
||||||
|
return new Object[][]{
|
||||||
|
{null, null, sl_v},
|
||||||
|
{null, i, sil_i},
|
||||||
|
{null, l_i, sil_i},
|
||||||
|
{l_it, null, sl_v},
|
||||||
|
{l_it, i, sil_i},
|
||||||
|
{li_it, l_i, sil_i},
|
||||||
|
{l_it, null, sil_i},
|
||||||
|
{li_it, null, sl_v},
|
||||||
|
{_it, l_i, si_i},
|
||||||
|
{_it, l_i, s_i}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "iterateParameters")
|
||||||
|
public static void testIterateParameters(MethodType it, MethodType in, MethodType bo) throws Throwable {
|
||||||
|
MethodHandle iterator = it == null ? null : MethodHandles.empty(it);
|
||||||
|
MethodHandle init = in == null ? null : MethodHandles.empty(in);
|
||||||
|
MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo));
|
||||||
|
MethodType lt = loop.type();
|
||||||
|
if (it == null && in == null) {
|
||||||
|
assertEquals(bo.dropParameterTypes(0, 1), lt);
|
||||||
|
} else if (it == null) {
|
||||||
|
if (in.parameterCount() == 0) {
|
||||||
|
assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt);
|
||||||
|
} else {
|
||||||
|
assertEquals(methodType(bo.returnType(), in.parameterArray()), lt);
|
||||||
|
}
|
||||||
|
} else if (in == null) {
|
||||||
|
assertEquals(methodType(bo.returnType(), it.parameterArray()), lt);
|
||||||
|
} else if (it.parameterCount() > in.parameterCount()) {
|
||||||
|
assertEquals(methodType(bo.returnType(), it.parameterArray()), lt);
|
||||||
|
} else if (it.parameterCount() < in.parameterCount()) {
|
||||||
|
assertEquals(methodType(bo.returnType(), in.parameterArray()), lt);
|
||||||
|
} else {
|
||||||
|
// both it, in present; with equal parameter list lengths
|
||||||
|
assertEquals(it.parameterList(), lt.parameterList());
|
||||||
|
assertEquals(in.parameterList(), lt.parameterList());
|
||||||
|
assertEquals(bo.returnType(), lt.returnType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public static void testIteratorSubclass() throws Throwable {
|
||||||
|
MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)),
|
||||||
|
null, MethodHandles.empty(methodType(void.class, String.class)));
|
||||||
|
assertEquals(methodType(void.class, List.class), loop.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BogusIterator implements Iterator {
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Object next() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class Empty {
|
static class Empty {
|
||||||
|
|
||||||
static void f() { }
|
static void f() { }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue