--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Tue Apr 23 14:09:54 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Tue Apr 23 22:55:09 2019 +0200
@@ -32,7 +32,9 @@
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
+import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
@@ -73,10 +75,11 @@
import java.util.stream.Collectors;
import jdk.internal.vm.compiler.collections.EconomicMap;
-import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecodes;
import org.graalvm.compiler.core.CompilerThreadFactory;
+import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.core.test.ReflectionOptionDescriptors;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.debug.GraalError;
@@ -86,11 +89,15 @@
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.test.CompileTheWorld.LibGraalParams.StackTraceBuffer;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser;
+import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+import jdk.internal.vm.compiler.libgraal.LibGraal;
+import jdk.internal.vm.compiler.libgraal.OptionsEncoder;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@@ -102,6 +109,7 @@
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.runtime.JVMCICompiler;
+import sun.misc.Unsafe;
/**
* This class implements compile-the-world functionality with JVMCI.
@@ -127,17 +135,19 @@
* Ignored if null.
*/
public static EconomicMap<OptionKey<?>, Object> parseOptions(String options) {
+ EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
if (options != null) {
EconomicMap<String, String> optionSettings = EconomicMap.create();
for (String optionSetting : options.split("\\s+|#")) {
OptionsParser.parseOptionSettingTo(optionSetting, optionSettings);
}
- EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
ServiceLoader<OptionDescriptors> loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader());
OptionsParser.parseOptions(optionSettings, values, loader);
- return values;
}
- return EconomicMap.create();
+ if (!values.containsKey(HighTier.Options.Inline)) {
+ values.put(HighTier.Options.Inline, false);
+ }
+ return values;
}
private final HotSpotJVMCIRuntime jvmciRuntime;
@@ -165,6 +175,13 @@
*/
private final int stopAt;
+ /**
+ * Max classes to compile.
+ *
+ * @see Options#MaxClasses
+ */
+ private final int maxClasses;
+
/** Only compile methods matching one of the filters in this array if the array is non-null. */
private final MethodFilter[] methodFilters;
@@ -186,8 +203,130 @@
private ThreadPoolExecutor threadPool;
- private OptionValues currentOptions;
- private final UnmodifiableEconomicMap<OptionKey<?>, Object> compilationOptions;
+ /**
+ * Values for {@link CompileTheWorld.Options}.
+ */
+ private final OptionValues harnessOptions;
+
+ /**
+ * Option values used during compilation.
+ */
+ private final OptionValues compilerOptions;
+
+ /**
+ * Manages native memory buffers for passing arguments into libgraal and receiving return
+ * values. The native memory buffers are freed when this object is {@linkplain #close() closed}.
+ */
+ static class LibGraalParams implements AutoCloseable {
+
+ static {
+ LibGraal.registerNativeMethods(HotSpotJVMCIRuntime.runtime(), CompileTheWorld.class);
+ }
+
+ /**
+ * Native memory containing {@linkplain OptionsEncoder encoded} {@link OptionValues}.
+ */
+ static class OptionsBuffer {
+ private long address;
+ final int size;
+ final int hash;
+
+ OptionsBuffer(OptionValues options) {
+ Map<String, Object> map = new HashMap<>();
+ UnmodifiableMapCursor<OptionKey<?>, Object> cursor = options.getMap().getEntries();
+ while (cursor.advance()) {
+ final OptionKey<?> key = cursor.getKey();
+ Object value = cursor.getValue();
+ map.put(key.getName(), value);
+ }
+
+ byte[] encoded = OptionsEncoder.encode(map);
+ size = encoded.length;
+ hash = Arrays.hashCode(encoded);
+ address = UNSAFE.allocateMemory(encoded.length);
+ UNSAFE.copyMemory(encoded, ARRAY_BYTE_BASE_OFFSET, null, address, size);
+ }
+
+ long getAddress() {
+ if (address == 0) {
+ throw new IllegalStateException();
+ }
+ return address;
+ }
+
+ void free() {
+ if (address != 0) {
+ UNSAFE.freeMemory(address);
+ address = 0;
+ }
+ }
+ }
+
+ /**
+ * Manages native memory for receiving a {@linkplain Throwable#printStackTrace() stack
+ * trace} from libgraal serialized via {@link ByteArrayOutputStream} to a byte array.
+ */
+ static class StackTraceBuffer {
+ final int size;
+ private long address;
+
+ StackTraceBuffer(int size) {
+ this.size = size;
+ address = UNSAFE.allocateMemory(size);
+ }
+
+ void free() {
+ if (address != 0L) {
+ UNSAFE.freeMemory(address);
+ address = 0L;
+ }
+ }
+
+ long getAddress() {
+ if (address == 0) {
+ throw new IllegalStateException();
+ }
+ return address;
+ }
+ }
+
+ final OptionsBuffer options;
+
+ private final List<StackTraceBuffer> stackTraceBuffers = new ArrayList<>();
+
+ /**
+ * Gets a stack trace buffer for the current thread.
+ */
+ StackTraceBuffer getStackTraceBuffer() {
+ return stackTraceBuffer.get();
+ }
+
+ private final ThreadLocal<StackTraceBuffer> stackTraceBuffer = new ThreadLocal<StackTraceBuffer>() {
+ @Override
+ protected StackTraceBuffer initialValue() {
+ StackTraceBuffer buffer = new StackTraceBuffer(10_000);
+ synchronized (stackTraceBuffers) {
+ stackTraceBuffers.add(buffer);
+ }
+ return buffer;
+ }
+ };
+
+ LibGraalParams(OptionValues options) {
+ this.options = new OptionsBuffer(options);
+ }
+
+ @Override
+ public void close() {
+ options.free();
+ synchronized (stackTraceBuffers) {
+ for (StackTraceBuffer buffer : stackTraceBuffers) {
+ buffer.free();
+ }
+ stackTraceBuffers.clear();
+ }
+ }
+ }
/**
* Creates a compile-the-world instance.
@@ -195,73 +334,99 @@
* @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile
* @param startAt index of the class file to start compilation at
* @param stopAt index of the class file to stop compilation at
+ * @param maxClasses maximum number of classes to process
* @param methodFilters
* @param excludeMethodFilters
+ * @param harnessOptions values for {@link CompileTheWorld.Options}
+ * @param compilerOptions option values used by the compiler
*/
- public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters,
- boolean verbose, OptionValues initialOptions, EconomicMap<OptionKey<?>, Object> compilationOptions) {
+ public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime,
+ HotSpotGraalCompiler compiler,
+ String files,
+ int startAt,
+ int stopAt,
+ int maxClasses,
+ String methodFilters,
+ String excludeMethodFilters,
+ boolean verbose,
+ OptionValues harnessOptions,
+ OptionValues compilerOptions) {
this.jvmciRuntime = jvmciRuntime;
this.compiler = compiler;
this.inputClassPath = files;
- this.startAt = startAt;
- this.stopAt = stopAt;
+ this.startAt = Math.max(startAt, 1);
+ this.stopAt = Math.max(stopAt, 1);
+ this.maxClasses = Math.max(maxClasses, 1);
this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters);
this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters);
this.verbose = verbose;
- this.currentOptions = initialOptions;
+ this.harnessOptions = harnessOptions;
// Copy the initial options and add in any extra options
- EconomicMap<OptionKey<?>, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap());
- compilationOptionsCopy.putAll(compilationOptions);
+ EconomicMap<OptionKey<?>, Object> compilerOptionsMap = EconomicMap.create(compilerOptions.getMap());
// We want to see stack traces when a method fails to compile
- CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
- CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
+ CompilationBailoutAsFailure.putIfAbsent(compilerOptionsMap, true);
+ CompilationFailureAction.putIfAbsent(compilerOptionsMap, Print);
// By default only report statistics for the CTW threads themselves
- DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld");
- this.compilationOptions = compilationOptionsCopy;
+ DebugOptions.MetricsThreadFilter.putIfAbsent(compilerOptionsMap, "^CompileTheWorld");
+ this.compilerOptions = new OptionValues(compilerOptionsMap);
}
- public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) {
- this(jvmciRuntime, compiler, Options.Classpath.getValue(options),
- Options.StartAt.getValue(options),
- Options.StopAt.getValue(options),
- Options.MethodFilter.getValue(options),
- Options.ExcludeMethodFilter.getValue(options),
- Options.Verbose.getValue(options),
- options,
- parseOptions(Options.Config.getValue(options)));
+ public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime,
+ HotSpotGraalCompiler compiler,
+ OptionValues harnessOptions,
+ OptionValues compilerOptions) {
+ this(jvmciRuntime, compiler, Options.Classpath.getValue(harnessOptions),
+ Options.StartAt.getValue(harnessOptions),
+ Options.StopAt.getValue(harnessOptions),
+ Options.MaxClasses.getValue(harnessOptions),
+ Options.MethodFilter.getValue(harnessOptions),
+ Options.ExcludeMethodFilter.getValue(harnessOptions),
+ Options.Verbose.getValue(harnessOptions),
+ harnessOptions,
+ new OptionValues(compilerOptions, parseOptions(Options.Config.getValue(harnessOptions))));
}
/**
* Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath}
* equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used.
*/
+ @SuppressWarnings("try")
public void compile() throws Throwable {
- if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
- String bcpEntry = null;
- if (Java8OrEarlier) {
- final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
- for (int i = 0; i < entries.length && bcpEntry == null; i++) {
- String entry = entries[i];
- File entryFile = new File(entry);
- if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) {
- bcpEntry = entry;
+ try (LibGraalParams libgraal = LibGraal.isAvailable() ? new LibGraalParams(compilerOptions) : null) {
+ if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
+ String bcpEntry = null;
+ if (Java8OrEarlier) {
+ final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
+ for (int i = 0; i < entries.length && bcpEntry == null; i++) {
+ String entry = entries[i];
+ File entryFile = new File(entry);
+ if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) {
+ bcpEntry = entry;
+ }
}
+ if (bcpEntry == null) {
+ throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH));
+ }
+ } else {
+ bcpEntry = JRT_CLASS_PATH_ENTRY;
}
- if (bcpEntry == null) {
- throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH));
- }
+ compile(bcpEntry, libgraal);
} else {
- bcpEntry = JRT_CLASS_PATH_ENTRY;
+ compile(inputClassPath, libgraal);
}
- compile(bcpEntry);
- } else {
- compile(inputClassPath);
}
}
+ private AutoCloseable enterCompilation() {
+ if (!LibGraal.isAvailable()) {
+ return null;
+ }
+ return new LibGraalParams(compilerOptions);
+ }
+
public void println() {
println("");
}
@@ -486,6 +651,19 @@
return true;
}
+ private ClassPathEntry openClassPathEntry(String entry) throws IOException {
+ if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
+ return new JarClassPathEntry(entry);
+ } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
+ return new JRTClassPathEntry(entry, Options.LimitModules.getValue(harnessOptions));
+ } else {
+ if (!new File(entry).isDirectory()) {
+ return null;
+ }
+ return new DirClassPathEntry(entry);
+ }
+ }
+
/**
* Compiles all methods in all classes in a given class path.
*
@@ -493,23 +671,25 @@
* @throws IOException
*/
@SuppressWarnings("try")
- private void compile(String classPath) throws IOException {
+ private void compile(String classPath, LibGraalParams libgraal) throws IOException {
final String[] entries = classPath.split(File.pathSeparator);
long start = System.currentTimeMillis();
Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces();
- try {
- // compile dummy method to get compiler initialized outside of the
- // config debug override.
- HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(
- CompileTheWorld.class.getDeclaredMethod("dummy"));
- int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
- boolean useProfilingInfo = false;
- boolean installAsDefault = false;
- CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions);
- task.runCompilation();
- } catch (NoSuchMethodException | SecurityException e1) {
- printStackTrace(e1);
+ if (libgraal == null) {
+ try {
+ // compile dummy method to get compiler initialized outside of the
+ // config debug override.
+ HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(
+ CompileTheWorld.class.getDeclaredMethod("dummy"));
+ int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
+ boolean useProfilingInfo = false;
+ boolean installAsDefault = false;
+ CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault);
+ task.runCompilation(compilerOptions);
+ } catch (NoSuchMethodException | SecurityException e1) {
+ printStackTrace(e1);
+ }
}
/*
@@ -517,8 +697,8 @@
* DebugValueThreadFilter to filter on the thread names.
*/
int threadCount = 1;
- if (Options.MultiThreaded.getValue(currentOptions)) {
- threadCount = Options.Threads.getValue(currentOptions);
+ if (Options.MultiThreaded.getValue(harnessOptions)) {
+ threadCount = Options.Threads.getValue(harnessOptions);
if (threadCount == 0) {
threadCount = Runtime.getRuntime().availableProcessors();
}
@@ -526,26 +706,37 @@
running = true;
}
- OptionValues savedOptions = currentOptions;
- currentOptions = new OptionValues(compilationOptions);
threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new CompilerThreadFactory("CompileTheWorld"));
- try {
- for (int i = 0; i < entries.length; i++) {
- final String entry = entries[i];
+ int compileStartAt = startAt;
+ int compileStopAt = stopAt;
+ int compileStep = 1;
+ if (maxClasses != Integer.MAX_VALUE) {
+ int totalClassFileCount = 0;
+ for (String entry : entries) {
+ try (ClassPathEntry cpe = openClassPathEntry(entry)) {
+ if (cpe != null) {
+ totalClassFileCount += cpe.getClassNames().size();
+ }
+ }
+ }
- ClassPathEntry cpe;
- if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
- cpe = new JarClassPathEntry(entry);
- } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
- cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions));
- } else {
- if (!new File(entry).isDirectory()) {
- println("CompileTheWorld : Skipped classes in " + entry);
- println();
- continue;
- }
- cpe = new DirClassPathEntry(entry);
+ int lastClassFile = totalClassFileCount - 1;
+ compileStartAt = Math.min(startAt, lastClassFile);
+ compileStopAt = Math.min(stopAt, lastClassFile);
+ int range = compileStopAt - compileStartAt + 1;
+ if (maxClasses < range) {
+ compileStep = range / maxClasses;
+ }
+ }
+
+ for (int i = 0; i < entries.length; i++) {
+ final String entry = entries[i];
+ try (ClassPathEntry cpe = openClassPathEntry(entry)) {
+ if (cpe == null) {
+ println("CompileTheWorld : Skipped classes in " + entry);
+ println();
+ continue;
}
if (methodFilters == null || methodFilters.length == 0) {
@@ -565,12 +756,16 @@
for (String className : cpe.getClassNames()) {
// Are we done?
- if (classFileCounter >= stopAt) {
+ if (classFileCounter >= compileStopAt) {
break;
}
classFileCounter++;
+ if (compileStep > 1 && ((classFileCounter - compileStartAt) % compileStep) != 0) {
+ continue;
+ }
+
if (className.startsWith("jdk.management.") ||
className.startsWith("jdk.internal.cmm.*") ||
// GR-5881: The class initializer for
@@ -606,28 +801,29 @@
}
// Are we compiling this class?
- if (classFileCounter >= startAt) {
- println("CompileTheWorld (%d) : %s", classFileCounter, className);
+ if (classFileCounter >= compileStartAt) {
+ long start0 = System.currentTimeMillis();
// Compile each constructor/method in the class.
for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor);
if (canBeCompiled(javaMethod, constructor.getModifiers())) {
- compileMethod(javaMethod);
+ compileMethod(javaMethod, libgraal);
}
}
for (Method method : javaClass.getDeclaredMethods()) {
HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
if (canBeCompiled(javaMethod, method.getModifiers())) {
- compileMethod(javaMethod);
+ compileMethod(javaMethod, libgraal);
}
}
// Also compile the class initializer if it exists
HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer();
if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) {
- compileMethod(clinit);
+ compileMethod(clinit, libgraal);
}
+ println("CompileTheWorld (%d) : %s (%d ms)", classFileCounter, className, System.currentTimeMillis() - start0);
}
} catch (Throwable t) {
if (isClassIncluded(className)) {
@@ -636,10 +832,7 @@
}
}
}
- cpe.close();
}
- } finally {
- currentOptions = savedOptions;
}
if (!running) {
@@ -661,11 +854,12 @@
long elapsedTime = System.currentTimeMillis() - start;
println();
- if (Options.MultiThreaded.getValue(currentOptions)) {
- TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime,
+ int compiledClasses = classFileCounter > compileStartAt ? classFileCounter - compileStartAt : 0;
+ if (Options.MultiThreaded.getValue(harnessOptions)) {
+ TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), elapsedTime,
compileTime.get(), memoryUsed.get());
} else {
- TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get());
+ TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get());
}
// Apart from the main thread, there should be only be daemon threads
@@ -712,7 +906,7 @@
}
@SuppressWarnings("try")
- private void compileMethod(HotSpotResolvedJavaMethod method) throws InterruptedException, ExecutionException {
+ private void compileMethod(HotSpotResolvedJavaMethod method, LibGraalParams libgraal) throws InterruptedException, ExecutionException {
if (methodFilters != null && !MethodFilter.matches(methodFilters, method)) {
return;
}
@@ -723,13 +917,7 @@
@Override
public void run() {
waitToRun();
- OptionValues savedOptions = currentOptions;
- currentOptions = new OptionValues(compilationOptions);
- try {
- compileMethod(method, classFileCounter);
- } finally {
- currentOptions = savedOptions;
- }
+ compileMethod(method, classFileCounter, libgraal);
}
});
if (threadPool.getCorePoolSize() == 1) {
@@ -737,23 +925,66 @@
}
}
+ private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
+
+ static native long compileMethodInLibgraal(long isolateThread,
+ long methodHandle,
+ boolean useProfilingInfo,
+ boolean installAsDefault,
+ long optionsAddress,
+ int optionsSize,
+ int optionsHash,
+ long encodedThrowableBufferAddress,
+ int encodedThrowableBufferSize);
+
/**
* Compiles a method and gathers some statistics.
*/
- private void compileMethod(HotSpotResolvedJavaMethod method, int counter) {
+ private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) {
try {
long start = System.currentTimeMillis();
long allocatedAtStart = getCurrentThreadAllocatedBytes();
- int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
- HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
// For more stable CTW execution, disable use of profiling information
boolean useProfilingInfo = false;
boolean installAsDefault = false;
- CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions);
- task.runCompilation();
+ HotSpotInstalledCode installedCode;
+ if (libgraal != null) {
+ HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+ long methodHandle = LibGraal.translate(runtime, method);
+ long isolateThread = LibGraal.getIsolateThread();
+
+ StackTraceBuffer stackTraceBuffer = libgraal.getStackTraceBuffer();
+
+ long stackTraceBufferAddress = stackTraceBuffer.getAddress();
+ long installedCodeHandle = compileMethodInLibgraal(isolateThread,
+ methodHandle,
+ useProfilingInfo,
+ installAsDefault,
+ libgraal.options.getAddress(),
+ libgraal.options.size,
+ libgraal.options.hash,
+ stackTraceBufferAddress,
+ stackTraceBuffer.size);
+
+ installedCode = LibGraal.unhand(runtime, HotSpotInstalledCode.class, installedCodeHandle);
+ if (installedCode == null) {
+ int length = UNSAFE.getInt(stackTraceBufferAddress);
+ byte[] data = new byte[length];
+ UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length);
+ String stackTrace = new String(data).trim();
+ println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
+ println(stackTrace);
+ }
+
+ } else {
+ int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
+ HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
+ CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault);
+ task.runCompilation(compilerOptions);
+ installedCode = task.getInstalledCode();
+ }
// Invalidate the generated code so the code cache doesn't fill up
- HotSpotInstalledCode installedCode = task.getInstalledCode();
if (installedCode != null) {
installedCode.invalidate();
}
@@ -799,13 +1030,12 @@
}
static class Options {
- // @formatter:off
public static final OptionKey<Boolean> Help = new OptionKey<>(false);
public static final OptionKey<String> Classpath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH);
public static final OptionKey<Boolean> Verbose = new OptionKey<>(true);
/**
- * Ignore Graal classes by default to avoid problems associated with compiling
- * snippets and method substitutions.
+ * Ignore Graal classes by default to avoid problems associated with compiling snippets and
+ * method substitutions.
*/
public static final OptionKey<String> LimitModules = new OptionKey<>("~jdk.internal.vm.compiler");
public static final OptionKey<Integer> Iterations = new OptionKey<>(1);
@@ -813,10 +1043,12 @@
public static final OptionKey<String> ExcludeMethodFilter = new OptionKey<>(null);
public static final OptionKey<Integer> StartAt = new OptionKey<>(1);
public static final OptionKey<Integer> StopAt = new OptionKey<>(Integer.MAX_VALUE);
+ public static final OptionKey<Integer> MaxClasses = new OptionKey<>(Integer.MAX_VALUE);
public static final OptionKey<String> Config = new OptionKey<>(null);
public static final OptionKey<Boolean> MultiThreaded = new OptionKey<>(false);
public static final OptionKey<Integer> Threads = new OptionKey<>(0);
+ // @formatter:off
static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class,
"Help", "List options and their help messages and then exit.",
"Classpath", "Class path denoting methods to compile. Default is to compile boot classes.",
@@ -826,21 +1058,24 @@
"Iterations", "The number of iterations to perform.",
"MethodFilter", "Only compile methods matching this filter.",
"ExcludeMethodFilter", "Exclude methods matching this filter from compilation.",
- "StartAt", "First class to consider for compilation.",
- "StopAt", "Last class to consider for compilation.",
- "Config", "Option value overrides to use during compile the world. For example, " +
- "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " +
- "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.",
+ "StartAt", "First class to consider for compilation (default = 1).",
+ "StopAt", "Last class to consider for compilation (default = <number of classes>).",
+ "MaxClasses", "Maximum number of classes to process (default = <number of classes>). " +
+ "Ignored if less than (StopAt - StartAt + 1).",
+ "Config", "Option values to use during compile the world compilations. For example, " +
+ "to disable partial escape analysis and print compilations specify " +
+ "'PartialEscapeAnalysis=false PrintCompilation=true'. " +
+ "Unless explicitly enabled with 'Inline=true' here, inlining is disabled.",
"MultiThreaded", "Run using multiple threads for compilation.",
"Threads", "Number of threads to use for multithreaded execution. Defaults to Runtime.getRuntime().availableProcessors().");
// @formatter:on
}
- public static OptionValues loadOptions(OptionValues initialValues) {
+ public static OptionValues loadHarnessOptions() {
EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
List<OptionDescriptors> loader = singletonList(DESCRIPTORS);
OptionsParser.parseOptions(extractEntries(System.getProperties(), "CompileTheWorld.", true), values, loader);
- OptionValues options = new OptionValues(initialValues, values);
+ OptionValues options = new OptionValues(values);
if (Options.Help.getValue(options)) {
options.printHelp(loader, System.out, "CompileTheWorld.");
System.exit(0);
@@ -853,14 +1088,14 @@
HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) jvmciRuntime.getCompiler();
HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
HotSpotCodeCacheProvider codeCache = graalRuntime.getHostProviders().getCodeCache();
- OptionValues options = loadOptions(graalRuntime.getOptions());
+ OptionValues harnessOptions = loadHarnessOptions();
- int iterations = Options.Iterations.getValue(options);
+ int iterations = Options.Iterations.getValue(harnessOptions);
for (int i = 0; i < iterations; i++) {
codeCache.resetCompilationStatistics();
TTY.println("CompileTheWorld : iteration " + i);
- CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, options);
+ CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, harnessOptions, graalRuntime.getOptions());
ctw.compile();
}
// This is required as non-daemon threads can be started by class initializers