1 /* |
1 /* |
2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
28 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print; |
28 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print; |
29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure; |
29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure; |
30 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; |
30 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; |
31 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; |
31 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; |
32 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; |
32 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; |
|
33 import static org.graalvm.compiler.hotspot.CompilationTask.CompilationTime; |
|
34 import static org.graalvm.compiler.hotspot.CompilationTask.CompiledAndInstalledBytecodes; |
33 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; |
35 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; |
|
36 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.InvalidateInstalledCode; |
34 import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; |
37 import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; |
35 |
38 |
36 import java.io.ByteArrayOutputStream; |
39 import java.io.ByteArrayOutputStream; |
37 import java.io.Closeable; |
40 import java.io.Closeable; |
38 import java.io.File; |
41 import java.io.File; |
79 import org.graalvm.compiler.bytecode.Bytecodes; |
82 import org.graalvm.compiler.bytecode.Bytecodes; |
80 import org.graalvm.compiler.core.CompilerThreadFactory; |
83 import org.graalvm.compiler.core.CompilerThreadFactory; |
81 import org.graalvm.compiler.core.phases.HighTier; |
84 import org.graalvm.compiler.core.phases.HighTier; |
82 import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; |
85 import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; |
83 import org.graalvm.compiler.debug.DebugOptions; |
86 import org.graalvm.compiler.debug.DebugOptions; |
|
87 import org.graalvm.compiler.debug.GlobalMetrics; |
84 import org.graalvm.compiler.debug.GraalError; |
88 import org.graalvm.compiler.debug.GraalError; |
85 import org.graalvm.compiler.debug.MethodFilter; |
89 import org.graalvm.compiler.debug.MethodFilter; |
|
90 import org.graalvm.compiler.debug.MetricKey; |
86 import org.graalvm.compiler.debug.TTY; |
91 import org.graalvm.compiler.debug.TTY; |
87 import org.graalvm.compiler.hotspot.CompilationTask; |
92 import org.graalvm.compiler.hotspot.CompilationTask; |
88 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; |
93 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; |
89 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; |
94 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; |
|
95 import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; |
90 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; |
96 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; |
91 import org.graalvm.compiler.hotspot.test.CompileTheWorld.LibGraalParams.StackTraceBuffer; |
97 import org.graalvm.compiler.hotspot.test.CompileTheWorld.LibGraalParams.StackTraceBuffer; |
92 import org.graalvm.compiler.options.OptionDescriptors; |
98 import org.graalvm.compiler.options.OptionDescriptors; |
93 import org.graalvm.compiler.options.OptionKey; |
99 import org.graalvm.compiler.options.OptionKey; |
94 import org.graalvm.compiler.options.OptionValues; |
100 import org.graalvm.compiler.options.OptionValues; |
95 import org.graalvm.compiler.options.OptionsParser; |
101 import org.graalvm.compiler.options.OptionsParser; |
96 import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; |
102 import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; |
97 import org.graalvm.compiler.serviceprovider.JavaVersionUtil; |
103 import org.graalvm.compiler.serviceprovider.JavaVersionUtil; |
|
104 import org.graalvm.compiler.test.ModuleSupport; |
98 import jdk.internal.vm.compiler.libgraal.LibGraal; |
105 import jdk.internal.vm.compiler.libgraal.LibGraal; |
99 import jdk.internal.vm.compiler.libgraal.LibGraalScope; |
106 import jdk.internal.vm.compiler.libgraal.LibGraalScope; |
100 import jdk.internal.vm.compiler.libgraal.OptionsEncoder; |
107 import jdk.internal.vm.compiler.libgraal.OptionsEncoder; |
101 |
108 |
102 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; |
109 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; |
381 Options.StartAt.getValue(harnessOptions), |
392 Options.StartAt.getValue(harnessOptions), |
382 Options.StopAt.getValue(harnessOptions), |
393 Options.StopAt.getValue(harnessOptions), |
383 Options.MaxClasses.getValue(harnessOptions), |
394 Options.MaxClasses.getValue(harnessOptions), |
384 Options.MethodFilter.getValue(harnessOptions), |
395 Options.MethodFilter.getValue(harnessOptions), |
385 Options.ExcludeMethodFilter.getValue(harnessOptions), |
396 Options.ExcludeMethodFilter.getValue(harnessOptions), |
386 Options.Verbose.getValue(harnessOptions), |
397 Options.Verbose.hasBeenSet(harnessOptions) ? Options.Verbose.getValue(harnessOptions) : !Options.MultiThreaded.getValue(harnessOptions), |
387 harnessOptions, |
398 harnessOptions, |
388 new OptionValues(compilerOptions, parseOptions(Options.Config.getValue(harnessOptions)))); |
399 new OptionValues(compilerOptions, parseOptions(Options.Config.getValue(harnessOptions)))); |
389 } |
400 } |
390 |
401 |
391 /** |
402 /** |
670 * @throws IOException |
674 * @throws IOException |
671 */ |
675 */ |
672 @SuppressWarnings("try") |
676 @SuppressWarnings("try") |
673 private void compile(String classPath, LibGraalParams libgraal) throws IOException { |
677 private void compile(String classPath, LibGraalParams libgraal) throws IOException { |
674 final String[] entries = classPath.split(File.pathSeparator); |
678 final String[] entries = classPath.split(File.pathSeparator); |
675 long start = System.currentTimeMillis(); |
679 long start = System.nanoTime(); |
676 Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces(); |
680 Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces(); |
677 |
681 |
678 if (libgraal == null) { |
682 if (libgraal == null) { |
679 try { |
683 try { |
680 // compile dummy method to get compiler initialized outside of the |
684 // compile dummy method to get compiler initialized outside of the |
800 } |
804 } |
801 |
805 |
802 // Are we compiling this class? |
806 // Are we compiling this class? |
803 if (classFileCounter >= compileStartAt) { |
807 if (classFileCounter >= compileStartAt) { |
804 |
808 |
805 long start0 = System.currentTimeMillis(); |
809 long start0 = System.nanoTime(); |
806 // Compile each constructor/method in the class. |
810 // Compile each constructor/method in the class. |
807 for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) { |
811 for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) { |
808 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor); |
812 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor); |
809 if (canBeCompiled(javaMethod, constructor.getModifiers())) { |
813 if (canBeCompiled(javaMethod, constructor.getModifiers())) { |
810 compileMethod(javaMethod, libgraal); |
814 compileMethod(javaMethod, libgraal); |
820 // Also compile the class initializer if it exists |
824 // Also compile the class initializer if it exists |
821 HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer(); |
825 HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer(); |
822 if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) { |
826 if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) { |
823 compileMethod(clinit, libgraal); |
827 compileMethod(clinit, libgraal); |
824 } |
828 } |
825 println("CompileTheWorld (%d) : %s (%d ms)", classFileCounter, className, System.currentTimeMillis() - start0); |
829 println("CompileTheWorld (%d) : %s (%d us)", classFileCounter, className, (System.nanoTime() - start0) / 1000); |
826 } |
830 } |
827 } catch (Throwable t) { |
831 } catch (Throwable t) { |
828 if (isClassIncluded(className)) { |
832 if (isClassIncluded(className)) { |
829 println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); |
833 println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); |
830 printStackTrace(t); |
834 printStackTrace(t); |
836 |
840 |
837 if (!running) { |
841 if (!running) { |
838 startThreads(); |
842 startThreads(); |
839 } |
843 } |
840 int wakeups = 0; |
844 int wakeups = 0; |
841 while (threadPool.getCompletedTaskCount() != threadPool.getTaskCount()) { |
845 long lastCompletedTaskCount = 0; |
|
846 for (long completedTaskCount = threadPool.getCompletedTaskCount(); completedTaskCount != threadPool.getTaskCount(); completedTaskCount = threadPool.getCompletedTaskCount()) { |
842 if (wakeups % 15 == 0) { |
847 if (wakeups % 15 == 0) { |
843 TTY.println("CompileTheWorld : Waiting for " + (threadPool.getTaskCount() - threadPool.getCompletedTaskCount()) + " compiles"); |
848 TTY.printf("CompileTheWorld : Waiting for %d compiles, just completed %d compiles%n", threadPool.getTaskCount() - completedTaskCount, completedTaskCount - lastCompletedTaskCount); |
|
849 lastCompletedTaskCount = completedTaskCount; |
844 } |
850 } |
845 try { |
851 try { |
846 threadPool.awaitTermination(1, TimeUnit.SECONDS); |
852 threadPool.awaitTermination(1, TimeUnit.SECONDS); |
847 wakeups++; |
853 wakeups++; |
848 } catch (InterruptedException e) { |
854 } catch (InterruptedException e) { |
849 } |
855 } |
850 } |
856 } |
|
857 threadPool.shutdown(); |
851 threadPool = null; |
858 threadPool = null; |
852 |
859 |
853 long elapsedTime = System.currentTimeMillis() - start; |
860 long elapsedTime = System.nanoTime() - start; |
854 |
861 |
855 println(); |
862 println(); |
856 int compiledClasses = classFileCounter > compileStartAt ? classFileCounter - compileStartAt : 0; |
863 int compiledClasses = classFileCounter > compileStartAt ? classFileCounter - compileStartAt : 0; |
857 if (Options.MultiThreaded.getValue(harnessOptions)) { |
864 if (Options.MultiThreaded.getValue(harnessOptions)) { |
858 TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), elapsedTime, |
865 TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), elapsedTime, |
859 compileTime.get(), memoryUsed.get()); |
866 compileTime.get() / 1000000, memoryUsed.get()); |
860 } else { |
867 } else { |
861 TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get()); |
868 TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get()); |
862 } |
869 } |
|
870 |
|
871 GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues(); |
|
872 EconomicMap<MetricKey, Long> map = metricValues.asKeyValueMap(); |
|
873 Long compiledAndInstalledBytecodes = map.get(CompiledAndInstalledBytecodes); |
|
874 Long compilationTime = map.get(CompilationTime); |
|
875 if (compiledAndInstalledBytecodes != null && compilationTime != null) { |
|
876 TTY.println("CompileTheWorld : Aggregate compile speed %d bytecodes per second (%d / %d)", (int) (compiledAndInstalledBytecodes / (compilationTime / 1000000000.0)), |
|
877 compiledAndInstalledBytecodes, compilationTime); |
|
878 } |
|
879 |
|
880 metricValues.print(compilerOptions); |
|
881 metricValues.clear(); |
863 |
882 |
864 // Apart from the main thread, there should be only be daemon threads |
883 // Apart from the main thread, there should be only be daemon threads |
865 // alive now. If not, then a class initializer has probably started |
884 // alive now. If not, then a class initializer has probably started |
866 // a thread that could cause a deadlock while trying to exit the VM. |
885 // a thread that could cause a deadlock while trying to exit the VM. |
867 // One known example of this is sun.tools.jconsole.OutputViewer which |
886 // One known example of this is sun.tools.jconsole.OutputViewer which |
940 * Compiles a method and gathers some statistics. |
963 * Compiles a method and gathers some statistics. |
941 */ |
964 */ |
942 @SuppressWarnings("try") |
965 @SuppressWarnings("try") |
943 private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) { |
966 private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) { |
944 try { |
967 try { |
945 long start = System.currentTimeMillis(); |
968 long start = System.nanoTime(); |
946 long allocatedAtStart = getCurrentThreadAllocatedBytes(); |
969 long allocatedAtStart = getCurrentThreadAllocatedBytes(); |
947 // For more stable CTW execution, disable use of profiling information |
970 // For more stable CTW execution, disable use of profiling information |
948 boolean useProfilingInfo = false; |
971 boolean useProfilingInfo = false; |
949 boolean installAsDefault = false; |
972 boolean installAsDefault = false; |
950 HotSpotInstalledCode installedCode; |
973 HotSpotInstalledCode installedCode; |
971 if (installedCode == null) { |
994 if (installedCode == null) { |
972 int length = UNSAFE.getInt(stackTraceBufferAddress); |
995 int length = UNSAFE.getInt(stackTraceBufferAddress); |
973 byte[] data = new byte[length]; |
996 byte[] data = new byte[length]; |
974 UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length); |
997 UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length); |
975 String stackTrace = new String(data).trim(); |
998 String stackTrace = new String(data).trim(); |
976 println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r")); |
999 println(true, String.format("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"))); |
977 println(stackTrace); |
1000 println(true, stackTrace); |
978 } |
1001 } |
979 } |
1002 } |
980 } else { |
1003 } else { |
981 int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; |
1004 int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; |
982 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); |
1005 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); |
984 task.runCompilation(compilerOptions); |
1007 task.runCompilation(compilerOptions); |
985 installedCode = task.getInstalledCode(); |
1008 installedCode = task.getInstalledCode(); |
986 } |
1009 } |
987 |
1010 |
988 // Invalidate the generated code so the code cache doesn't fill up |
1011 // Invalidate the generated code so the code cache doesn't fill up |
989 if (installedCode != null) { |
1012 if (installedCode != null && InvalidateInstalledCode.getValue(compilerOptions)) { |
990 installedCode.invalidate(); |
1013 installedCode.invalidate(); |
991 } |
1014 } |
992 |
1015 |
993 memoryUsed.getAndAdd(getCurrentThreadAllocatedBytes() - allocatedAtStart); |
1016 memoryUsed.getAndAdd(getCurrentThreadAllocatedBytes() - allocatedAtStart); |
994 compileTime.getAndAdd(System.currentTimeMillis() - start); |
1017 compileTime.getAndAdd(System.nanoTime() - start); |
995 compiledMethodsCounter.incrementAndGet(); |
1018 compiledMethodsCounter.incrementAndGet(); |
996 } catch (Throwable t) { |
1019 } catch (Throwable t) { |
997 // Catch everything and print a message |
1020 // Catch everything and print a message |
998 println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r")); |
1021 println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r")); |
999 printStackTrace(t); |
1022 printStackTrace(t); |
1046 public static final OptionKey<Integer> StopAt = new OptionKey<>(Integer.MAX_VALUE); |
1069 public static final OptionKey<Integer> StopAt = new OptionKey<>(Integer.MAX_VALUE); |
1047 public static final OptionKey<Integer> MaxClasses = new OptionKey<>(Integer.MAX_VALUE); |
1070 public static final OptionKey<Integer> MaxClasses = new OptionKey<>(Integer.MAX_VALUE); |
1048 public static final OptionKey<String> Config = new OptionKey<>(null); |
1071 public static final OptionKey<String> Config = new OptionKey<>(null); |
1049 public static final OptionKey<Boolean> MultiThreaded = new OptionKey<>(false); |
1072 public static final OptionKey<Boolean> MultiThreaded = new OptionKey<>(false); |
1050 public static final OptionKey<Integer> Threads = new OptionKey<>(0); |
1073 public static final OptionKey<Integer> Threads = new OptionKey<>(0); |
|
1074 public static final OptionKey<Boolean> InvalidateInstalledCode = new OptionKey<>(false); |
1051 |
1075 |
1052 // @formatter:off |
1076 // @formatter:off |
1053 static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, |
1077 static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, |
1054 "Help", "List options and their help messages and then exit.", |
1078 "Help", "List options and their help messages and then exit.", |
1055 "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.", |
1079 "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.", |
1056 "Verbose", "Verbose operation.", |
1080 "Verbose", "Verbose operation. Default is !MultiThreaded.", |
1057 "LimitModules", "Comma separated list of module names to which compilation should be limited. " + |
1081 "LimitModules", "Comma separated list of module names to which compilation should be limited. " + |
1058 "Module names can be prefixed with \"~\" to exclude the named module.", |
1082 "Module names can be prefixed with \"~\" to exclude the named module.", |
1059 "Iterations", "The number of iterations to perform.", |
1083 "Iterations", "The number of iterations to perform.", |
1060 "MethodFilter", "Only compile methods matching this filter.", |
1084 "MethodFilter", "Only compile methods matching this filter.", |
1061 "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.", |
1085 "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.", |
1096 codeCache.resetCompilationStatistics(); |
1120 codeCache.resetCompilationStatistics(); |
1097 TTY.println("CompileTheWorld : iteration " + i); |
1121 TTY.println("CompileTheWorld : iteration " + i); |
1098 |
1122 |
1099 CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, harnessOptions, graalRuntime.getOptions()); |
1123 CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, harnessOptions, graalRuntime.getOptions()); |
1100 ctw.compile(); |
1124 ctw.compile(); |
|
1125 if (iterations > 1) { |
|
1126 // Force a GC to encourage reclamation of nmethods when their InstalledCode |
|
1127 // reference has been dropped. |
|
1128 System.gc(); |
|
1129 } |
1101 } |
1130 } |
1102 // This is required as non-daemon threads can be started by class initializers |
1131 // This is required as non-daemon threads can be started by class initializers |
1103 System.exit(0); |
1132 System.exit(0); |
1104 } |
1133 } |
1105 } |
1134 } |