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 package org.graalvm.compiler.hotspot.test;
24
25 import static java.util.Collections.singletonList;
26 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
27 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout;
28 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
29 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
30 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
31 import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
32
33 import java.io.Closeable;
34 import java.io.File;
35 import java.io.IOException;
36 import java.lang.annotation.Annotation;
37 import java.lang.reflect.Constructor;
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Modifier;
40 import java.net.URI;
41 import java.net.URL;
42 import java.net.URLClassLoader;
43 import java.nio.file.FileSystem;
44 import java.nio.file.FileSystems;
45 import java.nio.file.FileVisitResult;
46 import java.nio.file.Files;
47 import java.nio.file.Path;
48 import java.nio.file.SimpleFileVisitor;
49 import java.nio.file.attribute.BasicFileAttributes;
51 import java.util.Arrays;
52 import java.util.Collections;
53 import java.util.Enumeration;
54 import java.util.HashSet;
55 import java.util.List;
56 import java.util.ServiceLoader;
57 import java.util.Set;
58 import java.util.concurrent.ExecutionException;
59 import java.util.concurrent.Future;
60 import java.util.concurrent.LinkedBlockingQueue;
61 import java.util.concurrent.ThreadPoolExecutor;
62 import java.util.concurrent.TimeUnit;
63 import java.util.concurrent.atomic.AtomicLong;
64 import java.util.jar.JarEntry;
65 import java.util.jar.JarFile;
66 import java.util.stream.Collectors;
67
68 import org.graalvm.compiler.api.replacements.Snippet;
69 import org.graalvm.compiler.bytecode.Bytecodes;
70 import org.graalvm.compiler.core.CompilerThreadFactory;
71 import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess;
72 import org.graalvm.compiler.core.test.ReflectionOptionDescriptors;
73 import org.graalvm.compiler.debug.DebugEnvironment;
74 import org.graalvm.compiler.debug.GraalDebugConfig;
75 import org.graalvm.compiler.debug.GraalError;
76 import org.graalvm.compiler.debug.MethodFilter;
77 import org.graalvm.compiler.debug.TTY;
78 import org.graalvm.compiler.debug.internal.MemUseTrackerImpl;
79 import org.graalvm.compiler.hotspot.CompilationTask;
80 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
81 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
82 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
83 import org.graalvm.compiler.options.OptionDescriptors;
84 import org.graalvm.compiler.options.OptionKey;
85 import org.graalvm.compiler.options.OptionValues;
86 import org.graalvm.compiler.options.OptionsParser;
87 import org.graalvm.compiler.serviceprovider.JDK9Method;
88 import org.graalvm.util.EconomicMap;
89 import org.graalvm.util.UnmodifiableEconomicMap;
90
91 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
92 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
93 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
94 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
95 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
96 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
97 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
98 import jdk.vm.ci.meta.ConstantPool;
202 this.inputClassPath = files;
203 this.startAt = startAt;
204 this.stopAt = stopAt;
205 this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters);
206 this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters);
207 this.verbose = verbose;
208 this.currentOptions = initialOptions;
209
210 // Copy the initial options and add in any extra options
211 EconomicMap<OptionKey<?>, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap());
212 compilationOptionsCopy.putAll(compilationOptions);
213
214 // We don't want the VM to exit when a method fails to compile...
215 ExitVMOnException.putIfAbsent(compilationOptionsCopy, false);
216
217 // ...but we want to see exceptions.
218 PrintBailout.putIfAbsent(compilationOptionsCopy, true);
219 PrintStackTraceOnException.putIfAbsent(compilationOptionsCopy, true);
220
221 // By default only report statistics for the CTW threads themselves
222 GraalDebugConfig.Options.DebugValueThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld");
223 this.compilationOptions = compilationOptionsCopy;
224 }
225
226 public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) {
227 this(jvmciRuntime, compiler, Options.Classpath.getValue(options),
228 Options.StartAt.getValue(options),
229 Options.StopAt.getValue(options),
230 Options.MethodFilter.getValue(options),
231 Options.ExcludeMethodFilter.getValue(options),
232 Options.Verbose.getValue(options),
233 options,
234 parseOptions(Options.Config.getValue(options)));
235 }
236
237 /**
238 * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath}
239 * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used.
240 */
241 public void compile() throws Throwable {
242 if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
494 } catch (NoSuchMethodException | SecurityException e1) {
495 printStackTrace(e1);
496 }
497
498 /*
499 * Always use a thread pool, even for single threaded mode since it simplifies the use of
500 * DebugValueThreadFilter to filter on the thread names.
501 */
502 int threadCount = 1;
503 if (Options.MultiThreaded.getValue(currentOptions)) {
504 threadCount = Options.Threads.getValue(currentOptions);
505 if (threadCount == 0) {
506 threadCount = Runtime.getRuntime().availableProcessors();
507 }
508 } else {
509 running = true;
510 }
511
512 OptionValues savedOptions = currentOptions;
513 currentOptions = new OptionValues(compilationOptions);
514 threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
515 new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() {
516 @Override
517 public GraalDebugConfig getDebugConfig() {
518 return DebugEnvironment.ensureInitialized(currentOptions, compiler.getGraalRuntime().getHostProviders().getSnippetReflection());
519 }
520 }));
521
522 try {
523 for (int i = 0; i < entries.length; i++) {
524 final String entry = entries[i];
525
526 ClassPathEntry cpe;
527 if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
528 cpe = new JarClassPathEntry(entry);
529 } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
530 cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions));
531 } else {
532 if (!new File(entry).isDirectory()) {
533 println("CompileTheWorld : Skipped classes in " + entry);
534 println();
535 continue;
536 }
537 cpe = new DirClassPathEntry(entry);
538 }
539
540 if (methodFilters == null || methodFilters.length == 0) {
686 OptionValues savedOptions = currentOptions;
687 currentOptions = new OptionValues(compilationOptions);
688 try {
689 compileMethod(method, classFileCounter);
690 } finally {
691 currentOptions = savedOptions;
692 }
693 }
694 });
695 if (threadPool.getCorePoolSize() == 1) {
696 task.get();
697 }
698 }
699
700 /**
701 * Compiles a method and gathers some statistics.
702 */
703 private void compileMethod(HotSpotResolvedJavaMethod method, int counter) {
704 try {
705 long start = System.currentTimeMillis();
706 long allocatedAtStart = MemUseTrackerImpl.getCurrentThreadAllocatedBytes();
707 int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
708 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
709 // For more stable CTW execution, disable use of profiling information
710 boolean useProfilingInfo = false;
711 boolean installAsDefault = false;
712 CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions);
713 task.runCompilation();
714
715 // Invalidate the generated code so the code cache doesn't fill up
716 HotSpotInstalledCode installedCode = task.getInstalledCode();
717 if (installedCode != null) {
718 installedCode.invalidate();
719 }
720
721 memoryUsed.getAndAdd(MemUseTrackerImpl.getCurrentThreadAllocatedBytes() - allocatedAtStart);
722 compileTime.getAndAdd(System.currentTimeMillis() - start);
723 compiledMethodsCounter.incrementAndGet();
724 } catch (Throwable t) {
725 // Catch everything and print a message
726 println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
727 printStackTrace(t);
728 }
729 }
730
731 /**
732 * Determines if a method should be compiled (Cf. CompilationPolicy::can_be_compiled).
733 *
734 * @return true if it can be compiled, false otherwise
735 */
736 private boolean canBeCompiled(HotSpotResolvedJavaMethod javaMethod, int modifiers) {
737 if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
738 return false;
739 }
740 GraalHotSpotVMConfig c = compiler.getGraalRuntime().getVMConfig();
741 if (c.dontCompileHugeMethods && javaMethod.getCodeSize() > c.hugeMethodLimit) {
|
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 package org.graalvm.compiler.hotspot.test;
24
25 import static java.util.Collections.singletonList;
26 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
27 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout;
28 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
29 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
30 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
31 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
32 import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
33
34 import java.io.Closeable;
35 import java.io.File;
36 import java.io.IOException;
37 import java.lang.annotation.Annotation;
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.Method;
40 import java.lang.reflect.Modifier;
41 import java.net.URI;
42 import java.net.URL;
43 import java.net.URLClassLoader;
44 import java.nio.file.FileSystem;
45 import java.nio.file.FileSystems;
46 import java.nio.file.FileVisitResult;
47 import java.nio.file.Files;
48 import java.nio.file.Path;
49 import java.nio.file.SimpleFileVisitor;
50 import java.nio.file.attribute.BasicFileAttributes;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.Enumeration;
55 import java.util.HashSet;
56 import java.util.List;
57 import java.util.ServiceLoader;
58 import java.util.Set;
59 import java.util.concurrent.ExecutionException;
60 import java.util.concurrent.Future;
61 import java.util.concurrent.LinkedBlockingQueue;
62 import java.util.concurrent.ThreadPoolExecutor;
63 import java.util.concurrent.TimeUnit;
64 import java.util.concurrent.atomic.AtomicLong;
65 import java.util.jar.JarEntry;
66 import java.util.jar.JarFile;
67 import java.util.stream.Collectors;
68
69 import org.graalvm.compiler.api.replacements.Snippet;
70 import org.graalvm.compiler.bytecode.Bytecodes;
71 import org.graalvm.compiler.core.CompilerThreadFactory;
72 import org.graalvm.compiler.core.test.ReflectionOptionDescriptors;
73 import org.graalvm.compiler.debug.DebugOptions;
74 import org.graalvm.compiler.debug.GraalError;
75 import org.graalvm.compiler.debug.MethodFilter;
76 import org.graalvm.compiler.debug.TTY;
77 import org.graalvm.compiler.hotspot.CompilationTask;
78 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
79 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
80 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
81 import org.graalvm.compiler.options.OptionDescriptors;
82 import org.graalvm.compiler.options.OptionKey;
83 import org.graalvm.compiler.options.OptionValues;
84 import org.graalvm.compiler.options.OptionsParser;
85 import org.graalvm.compiler.serviceprovider.JDK9Method;
86 import org.graalvm.util.EconomicMap;
87 import org.graalvm.util.UnmodifiableEconomicMap;
88
89 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
90 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
91 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
92 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
93 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
94 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
95 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
96 import jdk.vm.ci.meta.ConstantPool;
200 this.inputClassPath = files;
201 this.startAt = startAt;
202 this.stopAt = stopAt;
203 this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters);
204 this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters);
205 this.verbose = verbose;
206 this.currentOptions = initialOptions;
207
208 // Copy the initial options and add in any extra options
209 EconomicMap<OptionKey<?>, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap());
210 compilationOptionsCopy.putAll(compilationOptions);
211
212 // We don't want the VM to exit when a method fails to compile...
213 ExitVMOnException.putIfAbsent(compilationOptionsCopy, false);
214
215 // ...but we want to see exceptions.
216 PrintBailout.putIfAbsent(compilationOptionsCopy, true);
217 PrintStackTraceOnException.putIfAbsent(compilationOptionsCopy, true);
218
219 // By default only report statistics for the CTW threads themselves
220 DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld");
221 this.compilationOptions = compilationOptionsCopy;
222 }
223
224 public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) {
225 this(jvmciRuntime, compiler, Options.Classpath.getValue(options),
226 Options.StartAt.getValue(options),
227 Options.StopAt.getValue(options),
228 Options.MethodFilter.getValue(options),
229 Options.ExcludeMethodFilter.getValue(options),
230 Options.Verbose.getValue(options),
231 options,
232 parseOptions(Options.Config.getValue(options)));
233 }
234
235 /**
236 * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath}
237 * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used.
238 */
239 public void compile() throws Throwable {
240 if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
492 } catch (NoSuchMethodException | SecurityException e1) {
493 printStackTrace(e1);
494 }
495
496 /*
497 * Always use a thread pool, even for single threaded mode since it simplifies the use of
498 * DebugValueThreadFilter to filter on the thread names.
499 */
500 int threadCount = 1;
501 if (Options.MultiThreaded.getValue(currentOptions)) {
502 threadCount = Options.Threads.getValue(currentOptions);
503 if (threadCount == 0) {
504 threadCount = Runtime.getRuntime().availableProcessors();
505 }
506 } else {
507 running = true;
508 }
509
510 OptionValues savedOptions = currentOptions;
511 currentOptions = new OptionValues(compilationOptions);
512 threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new CompilerThreadFactory("CompileTheWorld"));
513
514 try {
515 for (int i = 0; i < entries.length; i++) {
516 final String entry = entries[i];
517
518 ClassPathEntry cpe;
519 if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
520 cpe = new JarClassPathEntry(entry);
521 } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
522 cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions));
523 } else {
524 if (!new File(entry).isDirectory()) {
525 println("CompileTheWorld : Skipped classes in " + entry);
526 println();
527 continue;
528 }
529 cpe = new DirClassPathEntry(entry);
530 }
531
532 if (methodFilters == null || methodFilters.length == 0) {
678 OptionValues savedOptions = currentOptions;
679 currentOptions = new OptionValues(compilationOptions);
680 try {
681 compileMethod(method, classFileCounter);
682 } finally {
683 currentOptions = savedOptions;
684 }
685 }
686 });
687 if (threadPool.getCorePoolSize() == 1) {
688 task.get();
689 }
690 }
691
692 /**
693 * Compiles a method and gathers some statistics.
694 */
695 private void compileMethod(HotSpotResolvedJavaMethod method, int counter) {
696 try {
697 long start = System.currentTimeMillis();
698 long allocatedAtStart = getCurrentThreadAllocatedBytes();
699 int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
700 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
701 // For more stable CTW execution, disable use of profiling information
702 boolean useProfilingInfo = false;
703 boolean installAsDefault = false;
704 CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions);
705 task.runCompilation();
706
707 // Invalidate the generated code so the code cache doesn't fill up
708 HotSpotInstalledCode installedCode = task.getInstalledCode();
709 if (installedCode != null) {
710 installedCode.invalidate();
711 }
712
713 memoryUsed.getAndAdd(getCurrentThreadAllocatedBytes() - allocatedAtStart);
714 compileTime.getAndAdd(System.currentTimeMillis() - start);
715 compiledMethodsCounter.incrementAndGet();
716 } catch (Throwable t) {
717 // Catch everything and print a message
718 println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
719 printStackTrace(t);
720 }
721 }
722
723 /**
724 * Determines if a method should be compiled (Cf. CompilationPolicy::can_be_compiled).
725 *
726 * @return true if it can be compiled, false otherwise
727 */
728 private boolean canBeCompiled(HotSpotResolvedJavaMethod javaMethod, int modifiers) {
729 if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
730 return false;
731 }
732 GraalHotSpotVMConfig c = compiler.getGraalRuntime().getVMConfig();
733 if (c.dontCompileHugeMethods && javaMethod.getCodeSize() > c.hugeMethodLimit) {
|