1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test VTBufferTest 26 * @summary Value Type interpreter value buffering test 27 * @library /test/lib 28 * @build ValueTypeGenerator 29 * @run main/othervm -Xint -XX:+EnableValhalla VTBufferTest generate-and-run 30 * @run main/othervm -Xint -XX:+EnableValhalla -XX:ValueTypesBufferMaxMemory=0 VTBufferTest generate-and-run 31 * @run main/othervm -Xint -XX:+EnableValhalla -XX:BigValueTypeThreshold=196 VTBufferTest generate-and-run 32 */ 33 34 /* This test generates its source code. 35 * To reproduce a run (for instance to investigate a failure), look at 36 * the test output and search for a line starting with "Seed=". The value 37 * at the end of the line is the seed used to generate the test. 38 * It possible to re-generate the same test with the following commande 39 * line: 40 * $ java <VMOptions> VTBufferTest generate-and-run -seed <seed> 41 * where <seed> is the seed value from the test output. 42 * The test source code is generated in the current directory with 43 * names Value[0-9][0-9].java and Loop.java. 44 * Once generated, the test can be run again without going through 45 * the generation phase with the following commande line: 46 * $ java <VMOptions> VTBufferTest run 47 */ 48 49 import javax.management.*; 50 import javax.tools.JavaCompiler; 51 import javax.tools.JavaFileObject; 52 import javax.tools.StandardJavaFileManager; 53 import javax.tools.ToolProvider; 54 import java.io.File; 55 import java.io.IOException; 56 import java.io.PrintWriter; 57 import java.lang.management.*; 58 import java.lang.reflect.InvocationTargetException; 59 import java.lang.reflect.Method; 60 import java.util.Arrays; 61 import java.util.List; 62 import java.util.Random; 63 import java.net.URL; 64 import java.net.URLClassLoader; 65 import java.util.ArrayList; 66 67 public class VTBufferTest implements Runnable { 68 static Random random; 69 static boolean generate; 70 static boolean execute; 71 static long seed = 0; 72 long startTime; 73 boolean verbose = false; 74 String[] valueNames; 75 File[] valueSources; 76 File[] loopSource; 77 78 79 static void usage() { 80 System.out.println("Usage:\n"); 81 System.out.println("\tVTBufferTest <command> [options]...\n"); 82 System.out.println("\nWhere <command> is one of the following: generate | generate-and-run | run\n"); 83 System.out.println("Where [options] can be: -seed <long value>\n"); 84 } 85 86 public static void main(String[] args) { 87 if (args.length < 1) { 88 usage(); 89 System.exit(-1); 90 } 91 92 if (args[0].compareTo("generate") == 0) { 93 generate = true; 94 execute = false; 95 } else if (args[0].compareTo("generate-and-run") == 0) { 96 generate = true; 97 execute = true; 98 } else if (args[0].compareTo("run") == 0) { 99 generate = false; 100 execute = true; 101 } else { 102 System.out.println("Unknown command\n"); 103 usage(); 104 System.exit(-1); 105 } 106 107 if (args.length > 1) { 108 int cursor = 1; 109 if (args[cursor].compareTo("-seed") == 0) { 110 if (args.length < 3) { 111 usage(); 112 System.exit(-1); 113 } 114 seed = Long.valueOf(args[cursor+1]); 115 cursor++; 116 } else { 117 System.out.println("Unknown option\n"); 118 usage(); 119 System.exit(-1); 120 } 121 } 122 123 if (generate) { 124 if (seed == 0) { 125 seed = System.nanoTime(); 126 } 127 random = new Random(seed); 128 System.out.println("Seed= " + seed); 129 } 130 131 VTBufferTest test = new VTBufferTest(true); 132 test.run(); 133 } 134 135 public VTBufferTest(boolean verbose) { 136 this.verbose = verbose; 137 } 138 139 static private String[] generateValueNames() { 140 int nvalues = random.nextInt(16) + 4; 141 String[] names = new String[nvalues]; 142 for (int i = 0; i < nvalues; i++) { 143 names[i] = new String("Value"+i); 144 } 145 return names; 146 } 147 148 static private File writeSource(String filename, String source) { 149 try{ 150 PrintWriter writer = new PrintWriter(filename, "UTF-8"); 151 writer.println(source); 152 writer.close(); 153 } catch (IOException e) { 154 throw new RuntimeException("Writing source file failed"); 155 } 156 return new File(filename); 157 } 158 159 static private File[] generateValueSources(String[] valueNames) { 160 File[] sources = new File[valueNames.length]; 161 for (int i = 0; i < valueNames.length; i++) { 162 int nfields = random.nextInt(6) + 1; 163 String s = ValueTypeGenerator.generateValueType(random, valueNames[i], nfields); 164 String filename = valueNames[i]+".java"; 165 sources[i] = writeSource(filename, s); 166 } 167 return sources; 168 } 169 170 static private File[] generateLoopSource(String[] names) { 171 StringBuilder sb = new StringBuilder(); 172 sb.append("// Seed = ").append(seed).append("\n"); 173 // class declaration 174 sb.append("public final class Loop {\n"); 175 sb.append("\n"); 176 177 sb.append("\tstatic {\n"); 178 int i = 0; 179 for (String name : names) { 180 sb.append("\t\t").append(names[i]).append(" lv").append(i).append(" = "); 181 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 182 sb.append("\t\tlv").append(i).append(".printLayout(System.out);\n"); 183 i++; 184 } 185 sb.append("\t}\n\n"); 186 187 // loop method 188 sb.append("\tstatic public void loop(int iterations) { \n"); 189 i = 0; 190 for (String name : names) { 191 sb.append("\t\t").append(names[i]).append(" lv").append(i).append(" = "); 192 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 193 i++; 194 } 195 sb.append("\t\tfor (int i = 0; i < iterations; i++) {\n"); 196 i = 0; 197 for (String name : names) { 198 sb.append("\t\t\tif (!").append(names[i]).append(".verify(lv").append(i).append("))\n"); 199 sb.append("\t\t\t\tthrow new RuntimeException(\"Error in ").append(names[i]).append("\");\n"); 200 i++; 201 } 202 i = 0; 203 for (String name : names) { 204 if (i != 0) { 205 sb.append("\t\t\tif (i % ").append(i).append(" != 0) {\n"); 206 sb.append("\t\t\t\tlv").append(i).append(" = "); 207 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 208 sb.append("\t\t\t}\n"); 209 } 210 i++; 211 } 212 sb.append("\t\t}\n"); 213 sb.append("\t}\n"); 214 sb.append("}\n"); 215 216 String source = sb.toString(); 217 218 File[] files = new File[1]; 219 files[0] = writeSource("Loop.java", source); 220 return files; 221 } 222 223 public void run() { 224 if (generate) { 225 valueNames = generateValueNames(); 226 valueSources = generateValueSources(valueNames); 227 loopSource = generateLoopSource(valueNames); 228 229 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 230 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 231 List<String> optionList = new ArrayList<String>(); 232 optionList.addAll(Arrays.asList("-classpath",".","-XDenableValueTypes")); 233 234 Iterable<? extends JavaFileObject> compilationUnits1 = 235 fileManager.getJavaFileObjectsFromFiles(Arrays.asList(valueSources)); 236 compiler.getTask(null, fileManager, null, optionList, null, compilationUnits1).call(); 237 238 Iterable<? extends JavaFileObject> compilationUnits2 = 239 fileManager.getJavaFileObjectsFromFiles(Arrays.asList(loopSource)); 240 compiler.getTask(null, fileManager, null, optionList, null, compilationUnits2).call(); 241 } 242 243 if (execute) { 244 startTime = ManagementFactory.getRuntimeMXBean().getUptime(); 245 246 ClassLoader cl = createClassLoader(); 247 try { 248 iterate(100, 5000, cl); 249 } catch(InvocationTargetException e) { 250 e.getCause().printStackTrace(); 251 System.exit(-1); 252 } 253 254 if (verbose) { 255 printVTBufferStats(); 256 257 System.out.println("\nGC Statistics:"); 258 List<GarbageCollectorMXBean> gcs = ManagementFactory.getGarbageCollectorMXBeans(); 259 for (GarbageCollectorMXBean gc : gcs) { 260 System.out.println("Name=" + gc.getName()); 261 System.out.println("GC counts=" + gc.getCollectionCount()); 262 System.out.println("GC time=" + gc.getCollectionTime() + "ms"); 263 } 264 265 System.out.println("\nHeap Statistics"); 266 List<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans(); 267 for (MemoryPoolMXBean memPool : memPools) { 268 if (memPool.getType() == MemoryType.HEAP) { 269 System.out.println("\nName: " + memPool.getName()); 270 System.out.println("Usage: " + memPool.getUsage()); 271 System.out.println("Collection Usage: " + memPool.getCollectionUsage()); 272 System.out.println("Peak Usage: " + memPool.getPeakUsage()); 273 } 274 } 275 } 276 } 277 } 278 279 280 ClassLoader createClassLoader() { 281 try{ 282 File file = new File("."); 283 URL url = file.toURI().toURL(); 284 URL[] urls = new URL[]{url}; 285 ClassLoader cl = new URLClassLoader(urls); 286 return cl; 287 } catch(Exception ex){ 288 ex.printStackTrace(); 289 } 290 return null; 291 } 292 293 public void iterate(int n, int m, ClassLoader cl) throws InvocationTargetException { 294 for (int i = 0; i < n; i++) { 295 Class loop = null; 296 try { 297 loop = Class.forName("Loop", true, cl); 298 } catch (ClassNotFoundException e) { 299 e.printStackTrace(); 300 } 301 Method method = null; 302 try { 303 method = loop.getMethod("loop", int.class); 304 } catch (NoSuchMethodException e) { 305 e.printStackTrace(); 306 return; 307 } 308 try { 309 method.invoke(null, m); 310 } catch (IllegalAccessException e) { 311 e.printStackTrace(); 312 return; 313 } catch (InvocationTargetException e) { 314 throw e; 315 } 316 } 317 } 318 319 public void printVTBufferStats() { 320 MBeanServerConnection mbs = ManagementFactory.getPlatformMBeanServer(); 321 String MBeanName = "com.sun.management:type=DiagnosticCommand"; 322 ObjectName beanName; 323 try { 324 beanName = new ObjectName(MBeanName); 325 } catch (MalformedObjectNameException e) { 326 String message = "MBean not found: " + MBeanName; 327 throw new RuntimeException(message, e); 328 } 329 String result = null; 330 try { 331 result = (String)mbs.invoke(beanName,"vtbufferStats",new Object[0],new String[0]); 332 } catch(Exception e) { 333 e.printStackTrace(); 334 } 335 System.out.println(result); 336 } 337 }