1 package compiler.jvmci.compilerToVM; 2 3 import jdk.vm.ci.code.InstalledCode; 4 import jdk.vm.ci.code.InvalidInstalledCodeException; 5 import jdk.vm.ci.hotspot.CompilerToVMHelper; 6 import jdk.test.lib.Asserts; 7 import jdk.test.lib.Pair; 8 import sun.hotspot.code.NMethod; 9 10 import java.lang.reflect.Constructor; 11 import java.lang.reflect.Executable; 12 import java.lang.reflect.InvocationTargetException; 13 import java.lang.reflect.Method; 14 import java.lang.reflect.Modifier; 15 import java.util.ArrayList; 16 import java.util.HashMap; 17 import java.util.List; 18 import java.util.Map; 19 20 /* 21 * @test 22 * @bug 8136421 23 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" 24 * @library /testlibrary /../../test/lib / 25 * @compile ../common/CompilerToVMHelper.java 26 * @build sun.hotspot.WhiteBox 27 * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest 28 * @run main ClassFileInstaller sun.hotspot.WhiteBox 29 * sun.hotspot.WhiteBox$WhiteBoxPermission 30 * jdk.vm.ci.hotspot.CompilerToVMHelper 31 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 32 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 33 * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest 34 */ 35 36 public class ExecuteInstalledCodeTest { 37 38 39 public static void main(String[] args) { 40 ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest(); 41 List<CompileCodeTestCase> testCases = new ArrayList<>(); 42 testCases.addAll(CompileCodeTestCase.generate(/* bci = */ -1)); 43 testCases .stream() 44 // ignore <init> of abstract class -- 8138793 45 .filter(e -> !(e.executable instanceof Constructor 46 && Modifier.isAbstract( 47 e.executable.getDeclaringClass() 48 .getModifiers()))) 49 .forEach(test::checkSanity); 50 } 51 52 private void checkSanity(CompileCodeTestCase testCase) { 53 System.out.println(testCase); 54 // to have a clean state 55 testCase.deoptimize(); 56 Pair<Object, ? extends Throwable> reflectionResult; 57 Object[] args = getArguments(testCase.executable); 58 reflectionResult = invoke(testCase, args); 59 NMethod nMethod = testCase.compile(); 60 if (nMethod == null) { 61 throw new Error(testCase + " : nmethod is null"); 62 } 63 InstalledCode installedCode = new InstalledCode( 64 testCase.executable.getName()); 65 installedCode.setAddress(nMethod.address); 66 Object result = null; 67 Throwable expectedException = reflectionResult.second; 68 boolean gotException = true; 69 try { 70 args = addReceiver(testCase, args); 71 result = CompilerToVMHelper.executeInstalledCode( 72 args, installedCode); 73 if (testCase.executable instanceof Constructor) { 74 // <init> doesn't have return value, it changes receiver 75 result = args[0]; 76 } 77 gotException = false; 78 } catch (InvalidInstalledCodeException e) { 79 throw new AssertionError( 80 testCase + " : unexpected InvalidInstalledCodeException", e); 81 } catch (Throwable t) { 82 if (expectedException == null) { 83 throw new AssertionError(testCase 84 + " : got unexpected execption : " + t.getMessage(), t); 85 } 86 87 if (expectedException.getClass() != t.getClass()) { 88 System.err.println("exception from CompilerToVM:"); 89 t.printStackTrace(); 90 System.err.println("exception from reflection:"); 91 expectedException.printStackTrace(); 92 throw new AssertionError(String.format( 93 "%s : got unexpected different exceptions : %s != %s", 94 testCase, expectedException.getClass(), t.getClass())); 95 } 96 } 97 98 Asserts.assertEQ(reflectionResult.first, result, testCase 99 + " : different return value"); 100 if (!gotException) { 101 Asserts.assertNull(expectedException, testCase 102 + " : expected exception hasn't been thrown"); 103 } 104 } 105 106 private Object[] addReceiver(CompileCodeTestCase testCase, Object[] args) { 107 if (!Modifier.isStatic(testCase.executable.getModifiers())) { 108 // add instance as 0th arg 109 Object[] newArgs = new Object[args.length + 1]; 110 newArgs[0] = getReciever(testCase); 111 System.arraycopy(args, 0, newArgs, 1, args.length); 112 args = newArgs; 113 } 114 return args; 115 } 116 117 private Object getReciever(CompileCodeTestCase testCase) { 118 return CompileCodeTestCase.RECEIVERS.get( 119 testCase.executable.getDeclaringClass()); 120 } 121 122 public Pair<Object, ? extends Throwable> invoke( 123 CompileCodeTestCase testCase, Object[] args) { 124 Executable executable = testCase.executable; 125 boolean old = executable.isAccessible(); 126 executable.setAccessible(true); 127 try { 128 try { 129 if (executable instanceof Method) { 130 Method m = (Method) executable; 131 return new Pair<>(m.invoke(getReciever(testCase), args), null); 132 } 133 134 if (executable instanceof Constructor) { 135 Constructor c = (Constructor) executable; 136 return new Pair<>(c.newInstance(args), null); 137 } 138 } catch (InvocationTargetException e) { 139 return new Pair<>(null, e.getCause()); 140 } catch (Throwable e) { 141 return new Pair<>(null, e); 142 } 143 } finally { 144 executable.setAccessible(old); 145 } 146 throw new Error(executable + " has unsupported type " 147 + executable.getClass()); 148 } 149 150 private Object[] getArguments(Executable method) { 151 Class<?>[] params = method.getParameterTypes(); 152 Object[] result = new Object[params.length]; 153 int i = 0; 154 for (Class<?> aClass : params) { 155 result[i++] = getArgument(aClass); 156 } 157 return result; 158 } 159 private static Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>(); 160 static { 161 DEFAULT_VALUES.put(boolean.class, false); 162 DEFAULT_VALUES.put(byte.class, (byte) 0); 163 DEFAULT_VALUES.put(short.class, (short) 0); 164 DEFAULT_VALUES.put(char.class, '\0'); 165 DEFAULT_VALUES.put(int.class, 0); 166 DEFAULT_VALUES.put(long.class, 0L); 167 DEFAULT_VALUES.put(float.class, 0.0f); 168 DEFAULT_VALUES.put(double.class, 0.0d); 169 } 170 private Object getArgument(Class<?> aClass) { 171 if (aClass.isPrimitive()) { 172 return DEFAULT_VALUES.get(aClass); 173 } 174 return null; 175 } 176 }