8b28ad6efe
Reviewed-by: alanb, jcbeyler
223 lines
9.0 KiB
Java
223 lines
9.0 KiB
Java
/*
|
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/* @test
|
|
* @summary unit tests for java.lang.invoke.MethodHandles
|
|
* @library /test/lib /java/lang/invoke/common
|
|
* @compile MethodHandlesTest.java MethodHandlesInvokersTest.java remote/RemoteExample.java
|
|
* @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
|
|
* -XX:-VerifyDependencies
|
|
* -esa
|
|
* test.java.lang.invoke.MethodHandlesInvokersTest
|
|
*/
|
|
|
|
package test.java.lang.invoke;
|
|
|
|
import org.junit.*;
|
|
import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
|
|
|
|
import java.lang.invoke.CallSite;
|
|
import java.lang.invoke.MethodHandle;
|
|
import java.lang.invoke.MethodHandles;
|
|
import java.lang.invoke.MethodType;
|
|
import java.lang.invoke.MutableCallSite;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
public class MethodHandlesInvokersTest extends MethodHandlesTest {
|
|
|
|
@Test // SLOW
|
|
public void testInvokers() throws Throwable {
|
|
CodeCacheOverflowProcessor.runMHTest(this::testInvokers0);
|
|
}
|
|
|
|
public void testInvokers0() throws Throwable {
|
|
if (CAN_SKIP_WORKING) return;
|
|
startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
|
|
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
|
|
Set<MethodType> done = new HashSet<>();
|
|
for (int i = 0; i <= 6; i++) {
|
|
if (CAN_TEST_LIGHTLY && i > 3) break;
|
|
MethodType gtype = MethodType.genericMethodType(i);
|
|
for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
|
|
for (int j = -1; j < i; j++) {
|
|
MethodType type = gtype;
|
|
if (j < 0)
|
|
type = type.changeReturnType(argType);
|
|
else if (argType == void.class)
|
|
continue;
|
|
else
|
|
type = type.changeParameterType(j, argType);
|
|
if (done.add(type))
|
|
testInvokersWithCatch(type);
|
|
MethodType vtype = type.changeReturnType(void.class);
|
|
if (done.add(vtype))
|
|
testInvokersWithCatch(vtype);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void testInvokersWithCatch(MethodType type) throws Throwable {
|
|
try {
|
|
testInvokers(type);
|
|
} catch (Throwable ex) {
|
|
System.out.println("*** testInvokers on "+type+" => ");
|
|
ex.printStackTrace(System.out);
|
|
}
|
|
}
|
|
|
|
public void testInvokers(MethodType type) throws Throwable {
|
|
if (verbosity >= 3)
|
|
System.out.println("test invokers for "+type);
|
|
int nargs = type.parameterCount();
|
|
boolean testRetCode = type.returnType() != void.class;
|
|
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
|
|
MethodType.genericMethodType(0, true));
|
|
assertTrue(target.isVarargsCollector());
|
|
target = target.asType(type);
|
|
Object[] args = randomArgs(type.parameterArray());
|
|
List<Object> targetPlusArgs = new ArrayList<>(Arrays.asList(args));
|
|
targetPlusArgs.add(0, target);
|
|
int code = (Integer) invokee(args);
|
|
Object log = logEntry("invokee", args);
|
|
assertEquals(log.hashCode(), code);
|
|
assertCalled("invokee", args);
|
|
MethodHandle inv;
|
|
Object result;
|
|
// exact invoker
|
|
countTest();
|
|
calledLog.clear();
|
|
inv = MethodHandles.exactInvoker(type);
|
|
result = inv.invokeWithArguments(targetPlusArgs);
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
// generic invoker
|
|
countTest();
|
|
inv = MethodHandles.invoker(type);
|
|
if (nargs <= 3 && type == type.generic()) {
|
|
calledLog.clear();
|
|
switch (nargs) {
|
|
case 0:
|
|
result = inv.invokeExact(target);
|
|
break;
|
|
case 1:
|
|
result = inv.invokeExact(target, args[0]);
|
|
break;
|
|
case 2:
|
|
result = inv.invokeExact(target, args[0], args[1]);
|
|
break;
|
|
case 3:
|
|
result = inv.invokeExact(target, args[0], args[1], args[2]);
|
|
break;
|
|
}
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
calledLog.clear();
|
|
result = inv.invokeWithArguments(targetPlusArgs);
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
// varargs invoker #0
|
|
calledLog.clear();
|
|
inv = MethodHandles.spreadInvoker(type, 0);
|
|
if (type.returnType() == Object.class) {
|
|
result = inv.invokeExact(target, args);
|
|
} else if (type.returnType() == void.class) {
|
|
result = null; inv.invokeExact(target, args);
|
|
} else {
|
|
result = inv.invokeWithArguments(target, (Object) args);
|
|
}
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
if (nargs >= 1 && type == type.generic()) {
|
|
// varargs invoker #1
|
|
calledLog.clear();
|
|
inv = MethodHandles.spreadInvoker(type, 1);
|
|
result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs));
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
if (nargs >= 2 && type == type.generic()) {
|
|
// varargs invoker #2
|
|
calledLog.clear();
|
|
inv = MethodHandles.spreadInvoker(type, 2);
|
|
result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
if (nargs >= 3 && type == type.generic()) {
|
|
// varargs invoker #3
|
|
calledLog.clear();
|
|
inv = MethodHandles.spreadInvoker(type, 3);
|
|
result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
for (int k = 0; k <= nargs; k++) {
|
|
// varargs invoker #0..N
|
|
if (CAN_TEST_LIGHTLY && (k > 1 || k < nargs - 1)) continue;
|
|
countTest();
|
|
calledLog.clear();
|
|
inv = MethodHandles.spreadInvoker(type, k);
|
|
MethodType expType = (type.dropParameterTypes(k, nargs)
|
|
.appendParameterTypes(Object[].class)
|
|
.insertParameterTypes(0, MethodHandle.class));
|
|
assertEquals(expType, inv.type());
|
|
List<Object> targetPlusVarArgs = new ArrayList<>(targetPlusArgs);
|
|
List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
|
|
Object[] tail = tailList.toArray();
|
|
tailList.clear(); tailList.add(tail);
|
|
result = inv.invokeWithArguments(targetPlusVarArgs);
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
|
|
// dynamic invoker
|
|
countTest();
|
|
CallSite site = new MutableCallSite(type);
|
|
inv = site.dynamicInvoker();
|
|
|
|
// see if we get the result of the original target:
|
|
try {
|
|
result = inv.invokeWithArguments(args);
|
|
assertTrue("should not reach here", false);
|
|
} catch (IllegalStateException ex) {
|
|
String msg = ex.getMessage();
|
|
assertTrue(msg, msg.contains("site"));
|
|
}
|
|
|
|
// set new target after invoker is created, to make sure we track target
|
|
site.setTarget(target);
|
|
calledLog.clear();
|
|
result = inv.invokeWithArguments(args);
|
|
if (testRetCode) assertEquals(code, result);
|
|
assertCalled("invokee", args);
|
|
}
|
|
}
|