--- /dev/null 2015-10-08 07:26:39.000000000 -1000 +++ new/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java 2015-10-08 07:26:39.000000000 -1000 @@ -0,0 +1,175 @@ +package compiler.jvmci.compilerToVM; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.test.lib.Asserts; +import jdk.test.lib.Pair; +import sun.hotspot.code.NMethod; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* + * @test + * @bug 8136421 + * @library /testlibrary /../../test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest + */ + +public class ExecuteInstalledCodeTest { + + + public static void main(String[] args) { + ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest(); + List testCases = new ArrayList<>(); + testCases.addAll(CompileCodeTestCase.generate(/* bci = */ -1)); + testCases .stream() + // ignore of abstract class -- 8138793 + .filter(e -> !(e.executable instanceof Constructor + && Modifier.isAbstract( + e.executable.getDeclaringClass() + .getModifiers()))) + .forEach(test::checkSanity); + } + + private void checkSanity(CompileCodeTestCase testCase) { + System.out.println(testCase); + // to have a clean state + testCase.deoptimize(); + Pair reflectionResult; + Object[] args = getArguments(testCase.executable); + reflectionResult = invoke(testCase, args); + NMethod nMethod = testCase.compile(); + if (nMethod == null) { + throw new Error(testCase + " : nmethod is null"); + } + InstalledCode installedCode = new InstalledCode( + testCase.executable.getName()); + installedCode.setAddress(nMethod.address); + Object result = null; + Throwable expectedException = reflectionResult.second; + boolean gotException = true; + try { + args = addReceiver(testCase, args); + result = CompilerToVMHelper.executeInstalledCode( + args, installedCode); + if (testCase.executable instanceof Constructor) { + // doesn't have return value, it changes receiver + result = args[0]; + } + gotException = false; + } catch (InvalidInstalledCodeException e) { + throw new AssertionError( + testCase + " : unexpected InvalidInstalledCodeException", e); + } catch (Throwable t) { + if (expectedException == null) { + throw new AssertionError(testCase + + " : got unexpected execption : " + t.getMessage(), t); + } + + if (expectedException.getClass() != t.getClass()) { + System.err.println("exception from CompilerToVM:"); + t.printStackTrace(); + System.err.println("exception from reflection:"); + expectedException.printStackTrace(); + throw new AssertionError(String.format( + "%s : got unexpected different exceptions : %s != %s", + testCase, expectedException.getClass(), t.getClass())); + } + } + + Asserts.assertEQ(reflectionResult.first, result, testCase + + " : different return value"); + if (!gotException) { + Asserts.assertNull(expectedException, testCase + + " : expected exception hasn't been thrown"); + } + } + + private Object[] addReceiver(CompileCodeTestCase testCase, Object[] args) { + if (!Modifier.isStatic(testCase.executable.getModifiers())) { + // add instance as 0th arg + Object[] newArgs = new Object[args.length + 1]; + newArgs[0] = getReciever(testCase); + System.arraycopy(args, 0, newArgs, 1, args.length); + args = newArgs; + } + return args; + } + + private Object getReciever(CompileCodeTestCase testCase) { + return CompileCodeTestCase.RECEIVERS.get( + testCase.executable.getDeclaringClass()); + } + + public Pair invoke( + CompileCodeTestCase testCase, Object[] args) { + Executable executable = testCase.executable; + boolean old = executable.isAccessible(); + executable.setAccessible(true); + try { + try { + if (executable instanceof Method) { + Method m = (Method) executable; + return new Pair<>(m.invoke(getReciever(testCase), args), null); + } + + if (executable instanceof Constructor) { + Constructor c = (Constructor) executable; + return new Pair<>(c.newInstance(args), null); + } + } catch (InvocationTargetException e) { + return new Pair<>(null, e.getCause()); + } catch (Throwable e) { + return new Pair<>(null, e); + } + } finally { + executable.setAccessible(old); + } + throw new Error(executable + " has unsupported type " + + executable.getClass()); + } + + private Object[] getArguments(Executable method) { + Class[] params = method.getParameterTypes(); + Object[] result = new Object[params.length]; + int i = 0; + for (Class aClass : params) { + result[i++] = getArgument(aClass); + } + return result; + } + private static Map, Object> DEFAULT_VALUES = new HashMap<>(); + static { + DEFAULT_VALUES.put(boolean.class, false); + DEFAULT_VALUES.put(byte.class, (byte) 0); + DEFAULT_VALUES.put(short.class, (short) 0); + DEFAULT_VALUES.put(char.class, '\0'); + DEFAULT_VALUES.put(int.class, 0); + DEFAULT_VALUES.put(long.class, 0L); + DEFAULT_VALUES.put(float.class, 0.0f); + DEFAULT_VALUES.put(double.class, 0.0d); + } + private Object getArgument(Class aClass) { + if (aClass.isPrimitive()) { + return DEFAULT_VALUES.get(aClass); + } + return null; + } +}