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 jvm.internal.value.*; 50 51 import javax.management.*; 52 import javax.tools.JavaCompiler; 53 import javax.tools.JavaFileObject; 54 import javax.tools.StandardJavaFileManager; 55 import javax.tools.ToolProvider; 56 import java.io.File; 57 import java.io.IOException; 58 import java.io.PrintWriter; 59 import java.lang.management.*; 60 import java.lang.reflect.InvocationTargetException; 61 import java.lang.reflect.Method; 62 import java.util.Arrays; 63 import java.util.List; 64 import java.util.Random; 65 import java.net.URL; 66 import java.net.URLClassLoader; 67 import java.util.ArrayList; 68 69 public class VTBufferTest implements Runnable { 70 static Random random; 71 static boolean generate; 72 static boolean execute; 73 static long seed = 0; 74 long startTime; 75 boolean verbose = false; 76 String[] valueNames; 77 File[] valueSources; 78 File[] loopSource; 79 80 81 static void usage() { 82 System.out.println("Usage:\n"); 83 System.out.println("\tVTBufferTest <command> [options]...\n"); 84 System.out.println("\nWhere <command> is one of the following: generate | generate-and-run | run\n"); 85 System.out.println("Where [options] can be: -seed <long value>\n"); 86 } 87 88 public static void main(String[] args) { 89 if (args.length < 1) { 90 usage(); 91 System.exit(-1); 92 } 93 94 if (args[0].compareTo("generate") == 0) { 95 generate = true; 96 execute = false; 97 } else if (args[0].compareTo("generate-and-run") == 0) { 98 generate = true; 99 execute = true; 100 } else if (args[0].compareTo("run") == 0) { 101 generate = false; 102 execute = true; 103 } else { 104 System.out.println("Unknown command\n"); 105 usage(); 106 System.exit(-1); 107 } 108 109 if (args.length > 1) { 110 int cursor = 1; 111 if (args[cursor].compareTo("-seed") == 0) { 112 if (args.length < 3) { 113 usage(); 114 System.exit(-1); 115 } 116 seed = Long.valueOf(args[cursor+1]); 117 cursor++; 118 } else { 119 System.out.println("Unknown option\n"); 120 usage(); 121 System.exit(-1); 122 } 123 } 124 125 if (generate) { 126 if (seed == 0) { 127 seed = System.nanoTime(); 128 } 129 random = new Random(seed); 130 System.out.println("Seed= " + seed); 131 } 132 133 VTBufferTest test = new VTBufferTest(true); 134 test.run(); 135 } 136 137 public VTBufferTest(boolean verbose) { 138 this.verbose = verbose; 139 } 140 141 static private String[] generateValueNames() { 142 int nvalues = random.nextInt(16) + 4; 143 String[] names = new String[nvalues]; 144 for (int i = 0; i < nvalues; i++) { 145 names[i] = new String("Value"+i); 146 } 147 return names; 148 } 149 150 static private File writeSource(String filename, String source) { 151 try{ 152 PrintWriter writer = new PrintWriter(filename, "UTF-8"); 153 writer.println(source); 154 writer.close(); 155 } catch (IOException e) { 156 throw new RuntimeException("Writing source file failed"); 157 } 158 return new File(filename); 159 } 160 161 static private File[] generateValueSources(String[] valueNames) { 162 File[] sources = new File[valueNames.length]; 163 for (int i = 0; i < valueNames.length; i++) { 164 int nfields = random.nextInt(6) + 1; 165 String s = ValueTypeGenerator.generateValueTypeNoObjectRef(random, valueNames[i], nfields); 166 String filename = valueNames[i]+".java"; 167 sources[i] = writeSource(filename, s); 168 } 169 return sources; 170 } 171 172 static private File[] generateLoopSource(String[] names) { 173 StringBuilder sb = new StringBuilder(); 174 sb.append("// Seed = ").append(seed).append("\n"); 175 // class declaration 176 sb.append("public final class Loop {\n"); 177 sb.append("\n"); 178 179 sb.append("\tstatic {\n"); 180 int i = 0; 181 for (String name : names) { 182 sb.append("\t\t").append(names[i]).append(" lv").append(i).append(" = "); 183 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 184 sb.append("\t\tlv").append(i).append(".printLayout(System.out);\n"); 185 i++; 186 } 187 sb.append("\t}\n\n"); 188 189 // loop method 190 sb.append("\tstatic public void loop(int iterations) { \n"); 191 i = 0; 192 for (String name : names) { 193 sb.append("\t\t").append(names[i]).append(" lv").append(i).append(" = "); 194 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 195 i++; 196 } 197 sb.append("\t\tfor (int i = 0; i < iterations; i++) {\n"); 198 i = 0; 199 for (String name : names) { 200 sb.append("\t\t\tif (!").append(names[i]).append(".verify(lv").append(i).append("))\n"); 201 sb.append("\t\t\t\tthrow new RuntimeException(\"Error in ").append(names[i]).append("\");\n"); 202 i++; 203 } 204 i = 0; 205 for (String name : names) { 206 if (i != 0) { 207 sb.append("\t\t\tif (i % ").append(i).append(" != 0) {\n"); 208 sb.append("\t\t\t\tlv").append(i).append(" = "); 209 sb.append(names[i]).append(".make").append(names[i]).append("();\n"); 210 sb.append("\t\t\t}\n"); 211 } 212 i++; 213 } 214 sb.append("\t\t}\n"); 215 sb.append("\t}\n"); 216 sb.append("}\n"); 217 218 String source = sb.toString(); 219 220 File[] files = new File[1]; 221 files[0] = writeSource("Loop.java", source); 222 return files; 223 } 224 225 public void run() { 226 if (generate) { 227 valueNames = generateValueNames(); 228 valueSources = generateValueSources(valueNames); 229 loopSource = generateLoopSource(valueNames); 230 231 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 232 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 233 List<String> optionList = new ArrayList<String>(); 234 optionList.addAll(Arrays.asList("-classpath",".","-XDenableValueTypes")); 235 236 Iterable<? extends JavaFileObject> compilationUnits1 = 237 fileManager.getJavaFileObjectsFromFiles(Arrays.asList(valueSources)); 238 compiler.getTask(null, fileManager, null, optionList, null, compilationUnits1).call(); 239 240 Iterable<? extends JavaFileObject> compilationUnits2 = 241 fileManager.getJavaFileObjectsFromFiles(Arrays.asList(loopSource)); 242 compiler.getTask(null, fileManager, null, optionList, null, compilationUnits2).call(); 243 } 244 245 if (execute) { 246 startTime = ManagementFactory.getRuntimeMXBean().getUptime(); 247 248 ClassLoader cl = createClassLoader(); 249 try { 250 iterate(100, 5000, cl); 251 } catch(InvocationTargetException e) { 252 e.getCause().printStackTrace(); 253 System.exit(-1); 254 } 255 256 if (verbose) { 257 printVTBufferStats(); 258 259 System.out.println("\nGC Statistics:"); 260 List<GarbageCollectorMXBean> gcs = ManagementFactory.getGarbageCollectorMXBeans(); 261 for (GarbageCollectorMXBean gc : gcs) { 262 System.out.println("Name=" + gc.getName()); 263 System.out.println("GC counts=" + gc.getCollectionCount()); 264 System.out.println("GC time=" + gc.getCollectionTime() + "ms"); 265 } 266 267 System.out.println("\nHeap Statistics"); 268 List<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans(); 269 for (MemoryPoolMXBean memPool : memPools) { 270 if (memPool.getType() == MemoryType.HEAP) { 271 System.out.println("\nName: " + memPool.getName()); 272 System.out.println("Usage: " + memPool.getUsage()); 273 System.out.println("Collection Usage: " + memPool.getCollectionUsage()); 274 System.out.println("Peak Usage: " + memPool.getPeakUsage()); 275 } 276 } 277 } 278 } 279 } 280 281 282 ClassLoader createClassLoader() { 283 try{ 284 File file = new File("."); 285 URL url = file.toURI().toURL(); 286 URL[] urls = new URL[]{url}; 287 ClassLoader cl = new URLClassLoader(urls); 288 return cl; 289 } catch(Exception ex){ 290 ex.printStackTrace(); 291 } 292 return null; 293 } 294 295 public void iterate(int n, int m, ClassLoader cl) throws InvocationTargetException { 296 for (int i = 0; i < n; i++) { 297 Class loop = null; 298 try { 299 loop = Class.forName("Loop", true, cl); 300 } catch (ClassNotFoundException e) { 301 e.printStackTrace(); 302 } 303 Method method = null; 304 try { 305 method = loop.getMethod("loop", int.class); 306 } catch (NoSuchMethodException e) { 307 e.printStackTrace(); 308 return; 309 } 310 try { 311 method.invoke(null, m); 312 } catch (IllegalAccessException e) { 313 e.printStackTrace(); 314 return; 315 } catch (InvocationTargetException e) { 316 throw e; 317 } 318 } 319 } 320 321 public void printVTBufferStats() { 322 MBeanServerConnection mbs = ManagementFactory.getPlatformMBeanServer(); 323 String MBeanName = "com.sun.management:type=DiagnosticCommand"; 324 ObjectName beanName; 325 try { 326 beanName = new ObjectName(MBeanName); 327 } catch (MalformedObjectNameException e) { 328 String message = "MBean not found: " + MBeanName; 329 throw new RuntimeException(message, e); 330 } 331 String result = null; 332 try { 333 result = (String)mbs.invoke(beanName,"vtbufferStats",new Object[0],new String[0]); 334 } catch(Exception e) { 335 e.printStackTrace(); 336 } 337 System.out.println(result); 338 } 339 }