diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index b33a9cb1e440..545af0571eff 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -2,6 +2,13 @@ This changelog summarizes newly introduced optimizations and other compiler related changes. +## GraalVM for JDK 25 (Internal Version 25.0.0) +* (GR-60088): This PR adds the `org.graalvm.nativeimage.libgraal` SDK module. With this module, all logic for building + libgraal has been moved into the compiler suite in a new `jdk.graal.compiler.libgraal` module + which has no dependency on Native Image internals. This + is required for Galahad CE where libgraal must be buildable from the Graal compiler sources in the OpenJDK + while using Native Image as an external tool. + ## GraalVM for JDK 24 (Internal Version 24.2.0) * (GR-57209): The default number of JVMCI threads is now the same as the number of C2 threads (`-XX:JVMCINativeLibraryThreadFraction=0.66`). This benefits the program warmup but could increase the maximum RSS. diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 7d66b610fffe..4aec44e0ad36 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -1485,6 +1485,7 @@ def __init__(self): __graal_config = GraalConfig() return __graal_config +# The jars needed for jargraal. def _jvmci_jars(): return [ 'compiler:GRAAL', diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index b5898666856b..9a6d793c496a 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -218,7 +218,6 @@ "jacoco" : "include", "jacocoExcludePackages" : [ "jdk.graal.compiler.test", - "org.graalvm.libgraal.jni", "jdk.graal.compiler.replacements", "jdk.graal.compiler.hotspot.test", "jdk.graal.compiler.replacements.test", @@ -472,13 +471,48 @@ "graalCompilerSourceEdition": "ignore", }, + # ------------- libgraal ------------- + + # See jdk.graal.compiler.core.common.LibGraalSupport for the SPI + # used by core compiler classes to access libgraal specific + # functionality without requiring the compiler classes to directly + # depend on libgraal specific modules. + "jdk.graal.compiler.libgraal" : { + "subDir" : "src", + "sourceDirs" : ["src"], + "workingSets" : "Graal", + "javaCompliance" : "21+", + "dependencies" : [ + "GRAAL", + "sdk:NATIVEIMAGE_LIBGRAAL", + "sdk:JNIUTILS", + "sdk:NATIVEBRIDGE" + ], + "requiresConcealed" : { + "java.base" : [ + "jdk.internal.module", + "jdk.internal.misc" + ], + "jdk.internal.vm.ci" : [ + "jdk.vm.ci.code", + "jdk.vm.ci.meta", + "jdk.vm.ci.runtime", + "jdk.vm.ci.services", + "jdk.vm.ci.hotspot", + ], + }, + "annotationProcessors" : [ + "truffle:TRUFFLE_LIBGRAAL_PROCESSOR", + ], + }, + "jdk.graal.compiler.libgraal.loader" : { "subDir" : "src", "sourceDirs" : ["src"], "workingSets" : "Graal", "javaCompliance" : "21+", "dependencies" : [ - "jdk.graal.compiler", + "sdk:NATIVEIMAGE_LIBGRAAL", ], "requiresConcealed" : { "java.base" : [ @@ -557,7 +591,8 @@ "moduleInfo" : { "name" : "jdk.graal.compiler", "exports" : [ - """* to com.oracle.graal.graal_enterprise, + """* to jdk.graal.compiler.libgraal, + com.oracle.graal.graal_enterprise, org.graalvm.nativeimage.pointsto, org.graalvm.nativeimage.builder, org.graalvm.nativeimage.foreign, @@ -583,6 +618,7 @@ "uses" : [ "jdk.graal.compiler.code.DisassemblerProvider", "jdk.graal.compiler.core.match.MatchStatementSet", + "jdk.graal.compiler.core.common.LibGraalSupport", "jdk.graal.compiler.debug.DebugHandlersFactory", "jdk.graal.compiler.debug.TTYStreamProvider", "jdk.graal.compiler.debug.PathUtilitiesProvider", @@ -634,6 +670,38 @@ }, }, + "LIBGRAAL_LOADER" : { + "subDir": "src", + "dependencies" : [ + "jdk.graal.compiler.libgraal.loader" + ], + "distDependencies" : [ + "sdk:NATIVEIMAGE_LIBGRAAL", + "GRAAL", + ], + "maven": False, + }, + + "LIBGRAAL": { + "moduleInfo" : { + "name" : "jdk.graal.compiler.libgraal", + }, + "subDir": "src", + "description" : "Module that builds libgraal", + "javaCompliance" : "21+", + "dependencies": [ + "jdk.graal.compiler.libgraal", + ], + "distDependencies": [ + "GRAAL", + "sdk:NATIVEIMAGE_LIBGRAAL", + "sdk:JNIUTILS", + "sdk:NATIVEIMAGE", + "sdk:NATIVEBRIDGE" + ], + "maven": False, + }, + "GRAAL_COMPILER_WHITEBOX_MICRO_BENCHMARKS" : { "subDir" : "src", "dependencies" : [ @@ -711,17 +779,6 @@ "graalCompilerSourceEdition": "ignore", }, - "LIBGRAAL_LOADER" : { - "subDir": "src", - "dependencies" : [ - "jdk.graal.compiler.libgraal.loader", - ], - "distDependencies" : [ - "GRAAL", - ], - "maven": False, - }, - "GRAAL_PROFDIFF_TEST" : { "subDir" : "src", "dependencies" : [ diff --git a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java similarity index 52% rename from compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoader.java rename to compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java index aaf39c51dd3b..2064a0fddede 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoader.java +++ b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,12 +22,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal; +package jdk.graal.compiler.libgraal.loader; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -35,6 +39,7 @@ import java.net.URLConnection; import java.net.URLStreamHandler; import java.nio.ByteBuffer; +import java.nio.file.Files; import java.nio.file.Path; import java.security.ProtectionDomain; import java.util.ArrayList; @@ -43,27 +48,43 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; +import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; -import jdk.graal.compiler.debug.GraalError; import jdk.internal.jimage.BasicImageReader; -import jdk.internal.jimage.ImageLocation; +import jdk.internal.module.ModulePath; import jdk.internal.module.Modules; /** - * A classloader, that reads class files and resources from a jimage file at image build time. + * A classloader that reads class files and resources from a jimage file and a module path at image + * build time. The {@code java.home} of the JDK containing the jimage can be obtained by converting + * the bytes of {@code getResourceAsStream("META-INF/libgraal.java.home")} to a string. */ -@SuppressWarnings("unused") @Platforms(Platform.HOSTED_ONLY.class) -final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalClassLoaderBase { +public final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalLoader { - private static final String JAVA_HOME_PROPERTY_KEY = "jdk.graal.internal.libgraal.javahome"; - private static final String JAVA_HOME_PROPERTY_VALUE = System.getProperty(JAVA_HOME_PROPERTY_KEY, System.getProperty("java.home")); + /** + * Name of the system property specifying the {@code java.home} of the JDK whose runtime image + * contains the Graal and JVMCI classes from which libgraal will be built. + */ + private static final String LIBGRAAL_JAVA_HOME_PROPERTY_NAME = "libgraal.java.home"; + + /** + * The {@code java.home} of the JDK whose runtime image contains the Graal and JVMCI classes + * from which libgraal will be built. + */ + private static final Path LIBGRAAL_JAVA_HOME = Path.of(System.getProperty(LIBGRAAL_JAVA_HOME_PROPERTY_NAME, System.getProperty("java.home"))); + + /** + * Name of the system property specifying a module path for the module(s) containing + * {@code LibGraalFeature} and its dependencies that are not available in the runtime image. + */ + private static final String LIBGRAAL_MODULE_PATH_PROPERTY_NAME = "libgraal.module.path"; /** * Reader for the image. @@ -71,15 +92,73 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla private final BasicImageReader imageReader; /** - * Map from the name of a resource (without module qualifier) to its path in the image. + * A resource located in the jimage file or on the module path. */ - private final Map resources = new HashMap<>(); + static abstract class Resource { + final String name; + + Resource(String name) { + this.name = name; + } + + /** + * Gets the bytes of the resource. + * + * @throws ClassNotFoundException if the bytes cannot be accessed + */ + abstract byte[] readBytes() throws ClassNotFoundException; + } /** - * Map from the {@linkplain Class#forName(String) name} of a class to the image path of its - * class file. + * A resource located in the jimage file. + */ + class ImageResource extends Resource { + ImageResource(String name) { + super(name); + } + + @Override + byte[] readBytes() throws ClassNotFoundException { + byte[] resource = imageReader.getResource(name); + if (resource == null) { + throw new ClassNotFoundException(name); + } + return resource; + } + } + + /** + * A resource located on the module path specified by + * {@link #LIBGRAAL_MODULE_PATH_PROPERTY_NAME}. + */ + static class ModulePathResource extends Resource { + private final ModuleReference mref; + + ModulePathResource(String name, ModuleReference mref) { + super(name); + this.mref = mref; + } + + @Override + byte[] readBytes() throws ClassNotFoundException { + try (ModuleReader reader = mref.open()) { + Optional oin = reader.open(name); + if (oin.isEmpty()) { + throw new ClassNotFoundException(name); + } + try (InputStream in = oin.get()) { + return in.readAllBytes(); + } + } catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + } + + /** + * Map from the name of a resource (without module qualifier) to its path in the image. */ - private final Map classes; + private final Map resources = new HashMap<>(); /** * Map from a service name to a list of providers. @@ -93,13 +172,12 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla private final Map modules; /** - * Modules in which Graal classes and their dependencies are defined. + * Modules containing classes that can be annotated by {@code LibGraalService}. */ private static final Set LIBGRAAL_MODULES = Set.of( "jdk.internal.vm.ci", - "org.graalvm.collections", - "org.graalvm.word", "jdk.graal.compiler", + "jdk.graal.compiler.libgraal", "org.graalvm.truffle.compiler", "com.oracle.graal.graal_enterprise"); @@ -107,11 +185,23 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla ClassLoader.registerAsParallelCapable(); } - public final Path libGraalJavaHome; + /** + * Converts the module path entry {@code s} to a {@link Path}. + * + * @throws RuntimeException if {@code s} does not denote a readable path + */ + Path parseModulePathEntry(String s) { + Path path = Path.of(s); + if (!Files.isReadable(path)) { + throw new RuntimeException("%s specified by the %s system property is not readable".formatted(path, LIBGRAAL_MODULE_PATH_PROPERTY_NAME)); + } + return path; + } + @SuppressWarnings("unused") public HostedLibGraalClassLoader() { - super(LibGraalClassLoader.LOADER_NAME, Feature.class.getClassLoader()); - libGraalJavaHome = Path.of(JAVA_HOME_PROPERTY_VALUE); + // This loader delegates to the class loader that loaded its own class. + super("LibGraalClassLoader", HostedLibGraalClassLoader.class.getClassLoader()); try { /* @@ -129,9 +219,8 @@ public HostedLibGraalClassLoader() { Modules.addExports(javaBaseModule, "jdk.internal.misc", unnamedModuleOfThisLoader); Map modulesMap = new HashMap<>(); - Map classesMap = new HashMap<>(); - Path imagePath = libGraalJavaHome.resolve(Path.of("lib", "modules")); + Path imagePath = LIBGRAAL_JAVA_HOME.resolve(Path.of("lib", "modules")); this.imageReader = BasicImageReader.open(imagePath); for (var entry : imageReader.getEntryNames()) { int secondSlash = entry.indexOf('/', 1); @@ -139,7 +228,7 @@ public HostedLibGraalClassLoader() { String module = entry.substring(1, secondSlash); if (LIBGRAAL_MODULES.contains(module)) { String resource = entry.substring(secondSlash + 1); - resources.put(resource, entry); + resources.put(resource, new ImageResource(entry)); if (resource.endsWith(".class")) { String className = resource.substring(0, resource.length() - ".class".length()).replace('/', '.'); if (resource.equals("module-info.class")) { @@ -148,7 +237,6 @@ public HostedLibGraalClassLoader() { services.computeIfAbsent(p.service(), k -> new ArrayList<>()).addAll(p.providers()); } } else { - classesMap.put(className, entry); modulesMap.put(className, module); } } @@ -156,29 +244,49 @@ public HostedLibGraalClassLoader() { } } + String prop = System.getProperty(LIBGRAAL_MODULE_PATH_PROPERTY_NAME); + if (prop != null) { + ModuleFinder libgraalModulePath = ModulePath.of(Stream.of(prop.split(File.pathSeparator)).map(this::parseModulePathEntry).toArray(Path[]::new)); + for (ModuleReference mr : libgraalModulePath.findAll()) { + ModuleDescriptor md = mr.descriptor(); + if (LIBGRAAL_MODULES.contains(md.name())) { + for (var p : md.provides()) { + services.computeIfAbsent(p.service(), k -> new ArrayList<>()).addAll(p.providers()); + } + try (ModuleReader reader = mr.open()) { + reader.list().forEach(entry -> { + resources.put(entry, new ModulePathResource(entry, mr)); + if (entry.endsWith(".class")) { + String className = entry.substring(0, entry.length() - ".class".length()).replace('/', '.'); + if (!entry.equals("module-info.class")) { + modulesMap.put(className, md.name()); + } + } + }); + } + } + } + } + modules = Map.copyOf(modulesMap); - classes = Map.copyOf(classesMap); } catch (IOException e) { - throw GraalError.shouldNotReachHere(e); + throw new RuntimeException(e); } } + /** + * Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the + * name of its enclosing module. + */ @Override - public Map getModules() { + public Map getClassModuleMap() { return modules; } - /* Allow image builder to perform registration action on each class this loader provides. */ - - @Override - public Set getAllClassNames() { - return classes.keySet(); - } - @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (!classes.containsKey(name)) { + if (!modules.containsKey(name)) { return super.loadClass(name, resolve); } synchronized (getClassLoadingLock(name)) { @@ -191,18 +299,14 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } @Override - protected Class findClass(final String name) - throws ClassNotFoundException { + protected Class findClass(final String name) throws ClassNotFoundException { String path = name.replace('.', '/').concat(".class"); - String pathInImage = resources.get(path); - if (pathInImage != null) { - ImageLocation location = imageReader.findLocation(pathInImage); - if (location != null) { - ByteBuffer bb = Objects.requireNonNull(imageReader.getResourceBuffer(location)); - ProtectionDomain pd = null; - return super.defineClass(name, bb, pd); - } + Resource resource = resources.get(path); + if (resource != null) { + ByteBuffer bb = ByteBuffer.wrap(resource.readBytes()); + ProtectionDomain pd = null; + return super.defineClass(name, bb, pd); } throw new ClassNotFoundException(name); } @@ -213,6 +317,12 @@ protected Class findClass(final String name) */ private static final String SERVICE_PROTOCOL = "service-config"; + /** + * Name of the protocol for accessing a file whose contents are the {@code java.home} of the JDK + * whose runtime image contains the Graal and JVMCI * classes from which libgraal will be built. + */ + private static final String LIBGRAAL_JAVA_HOME_PROTOCOL = "libgraal-java-home"; + /** * Name of the protocol for accessing entries in {@link #resources}. */ @@ -226,7 +336,14 @@ protected URL findResource(String name) { if (handler == null) { this.serviceHandler = handler = new ImageURLStreamHandler(); } - if (name.startsWith("META-INF/services/")) { + if (name.equals("META-INF/libgraal.java.home")) { + try { + var uri = new URI(LIBGRAAL_JAVA_HOME_PROTOCOL, "libgraal.java.home", null); + return URL.of(uri, handler); + } catch (URISyntaxException | MalformedURLException e) { + return null; + } + } else if (name.startsWith("META-INF/services/")) { String service = name.substring("META-INF/services/".length()); if (services.containsKey(service)) { try { @@ -237,8 +354,8 @@ protected URL findResource(String name) { } } } else { - String path = resources.get(name); - if (path != null) { + Resource resource = resources.get(name); + if (resource != null) { try { var uri = new URI(RESOURCE_PROTOCOL, name, null); return URL.of(uri, handler); @@ -261,22 +378,30 @@ protected Enumeration findResources(String name) throws IOException { /** * A {@link URLStreamHandler} for use with URLs returned by - * {@link HostedLibGraalClassLoader#findResource(java.lang.String)}. + * {@link HostedLibGraalClassLoader#findResource(String)}. */ private class ImageURLStreamHandler extends URLStreamHandler { @Override public URLConnection openConnection(URL u) { String protocol = u.getProtocol(); - if (protocol.equalsIgnoreCase(SERVICE_PROTOCOL)) { + if (protocol.equalsIgnoreCase(LIBGRAAL_JAVA_HOME_PROTOCOL)) { + if (!u.getPath().equals("libgraal.java.home")) { + throw new IllegalArgumentException(u.toString()); + } + return new ImageURLConnection(u, LIBGRAAL_JAVA_HOME.toString().getBytes()); + } else if (protocol.equalsIgnoreCase(SERVICE_PROTOCOL)) { List providers = services.get(u.getPath()); if (providers != null) { return new ImageURLConnection(u, String.join("\n", providers).getBytes()); } } else if (protocol.equalsIgnoreCase(RESOURCE_PROTOCOL)) { - String pathInImage = resources.get(u.getPath()); - if (pathInImage != null) { - byte[] bytes = Objects.requireNonNull(imageReader.getResource(pathInImage)); - return new ImageURLConnection(u, bytes); + Resource resource = resources.get(u.getPath()); + if (resource != null) { + try { + return new ImageURLConnection(u, resource.readBytes()); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(u.toString(), e); + } } } throw new IllegalArgumentException(u.toString()); @@ -316,24 +441,4 @@ public String getContentType() { return "application/octet-stream"; } } - - @Override - public HostedLibGraalClassLoader getClassLoader() { - return this; - } - - @Override - public LibGraalClassLoader getRuntimeClassLoader() { - return LibGraalClassLoader.singleton; - } -} - -public final class LibGraalClassLoader extends ClassLoader { - - static final String LOADER_NAME = "LibGraalClassLoader"; - static final LibGraalClassLoader singleton = new LibGraalClassLoader(); - - private LibGraalClassLoader() { - super(LOADER_NAME, null); - } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/META-INF/services/jdk.graal.compiler.core.common.LibGraalSupport b/compiler/src/jdk.graal.compiler.libgraal/src/META-INF/services/jdk.graal.compiler.core.common.LibGraalSupport new file mode 100644 index 000000000000..ba1273980c79 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/META-INF/services/jdk.graal.compiler.core.common.LibGraalSupport @@ -0,0 +1 @@ +jdk.graal.compiler.libgraal.LibGraalSupportImpl diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoaderBase.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java similarity index 60% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoaderBase.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java index 0fb49d052f7d..20a417c2431d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoaderBase.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java @@ -22,33 +22,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.graal.compiler.libgraal; -package jdk.graal.compiler.hotspot.libgraal; +import java.util.function.BooleanSupplier; +import java.util.stream.Stream; -import java.util.Map; -import java.util.Set; +import jdk.vm.ci.services.Services; -public interface LibGraalClassLoaderBase { - - /** - * @return instance of ClassLoader that implements this interface. - */ - ClassLoader getClassLoader(); - - /** - * @return instance of ClassLoader that should be seen at image-runtime if a class was loaded at - * image-buildtime by this classloader. - */ - ClassLoader getRuntimeClassLoader(); +/** + * Determines if the JDK runtime does not include JDK-8346781. + */ +public class BeforeJDK8346781 implements BooleanSupplier { - /** - * Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the - * name of its enclosing module. - */ - Map getModules(); + static final boolean VALUE = Stream.of(Services.class.getFields()).anyMatch(f -> f.getName().equals("IS_BUILDING_NATIVE_IMAGE")); - /** - * Get unmodifiable set of fully qualified names of all classes this loader can load. - */ - Set getAllClassNames(); + @Override + public boolean getAsBoolean() { + return VALUE; + } } diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetCompilerConfig.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java similarity index 74% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetCompilerConfig.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java index ad11fc4f03d3..a50337117424 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetCompilerConfig.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot; +package jdk.graal.compiler.libgraal; import java.io.BufferedReader; import java.io.IOException; @@ -35,27 +35,21 @@ import java.util.Set; import java.util.stream.Collectors; -import org.graalvm.collections.UnmodifiableEconomicMap; -import org.graalvm.collections.UnmodifiableMapCursor; - -import com.oracle.graal.pointsto.api.PointstoOptions; -import com.oracle.svm.core.option.HostedOptionKey; -import com.oracle.svm.core.option.RuntimeOptionKey; - import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.HotSpotGraalOptionValues; -import jdk.graal.compiler.hotspot.libgraal.CompilerConfig; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.hotspot.CompilerConfig; +import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.util.ObjectCopier; import org.graalvm.nativeimage.ImageInfo; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * Gets the map created in a JVM subprocess by running {@link CompilerConfig}. */ +@Platforms(Platform.HOSTED_ONLY.class) public class GetCompilerConfig { - private static final boolean DEBUG = Boolean.getBoolean("debug." + GetCompilerConfig.class.getName()); + private static final boolean DEBUG = Boolean.parseBoolean(GraalServices.getSavedProperty("debug." + GetCompilerConfig.class.getName())); /** * Result returned by {@link GetCompilerConfig#from}. @@ -102,12 +96,9 @@ private static boolean isInBootLayer(Path javaExe, String module) { * * @param javaHome the value of the {@code java.home} system property reported by a Java * installation directory that includes the Graal classes in its runtime image - * @param options the options passed to native-image */ - public static Result from(Path javaHome, OptionValues options) { + public static Result from(Path javaHome) { Path javaExe = GetJNIConfig.getJavaExe(javaHome); - UnmodifiableEconomicMap, Object> optionsMap = options.getMap(); - UnmodifiableMapCursor, Object> entries = optionsMap.getEntries(); Map> opens = Map.of( // Needed to reflect fields like // java.util.ImmutableCollections.EMPTY @@ -125,35 +116,25 @@ public static Result from(Path javaHome, OptionValues options) { "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-XX:-UseJVMCICompiler", // avoid deadlock with jargraal + + // Required to use Modules class + "--add-exports=java.base/jdk.internal.module=jdk.graal.compiler", addExports, - "-Djdk.vm.ci.services.aot=true", + "-Djdk.vm.ci.services.aot=true", // Remove after JDK-8346781 "-D%s=%s".formatted(ImageInfo.PROPERTY_IMAGE_CODE_KEY, ImageInfo.PROPERTY_IMAGE_CODE_VALUE_BUILDTIME))); - Module module = ObjectCopier.class.getModule(); - String target = module.isNamed() ? module.getName() : "ALL-UNNAMED"; for (var e : opens.entrySet()) { for (String source : e.getValue()) { - command.add("--add-opens=%s/%s=%s".formatted(e.getKey(), source, target)); - } - } - - // Propagate compiler options - while (entries.advance()) { - OptionKey key = entries.getKey(); - if (key instanceof RuntimeOptionKey || key instanceof HostedOptionKey) { - // Ignore Native Image options - continue; - } - if (key.getDescriptor().getDeclaringClass().getModule().equals(PointstoOptions.class.getModule())) { - // Ignore points-to analysis options - continue; + command.add("--add-opens=%s/%s=jdk.graal.compiler".formatted(e.getKey(), source)); } - command.add("-D%s%s=%s".formatted(HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, key.getName(), entries.getValue())); } command.add(CompilerConfig.class.getName()); - Path encodedConfigPath = Path.of(GetCompilerConfig.class.getSimpleName() + "_" + ProcessHandle.current().pid() + ".txt").toAbsolutePath(); + String base = GetCompilerConfig.class.getSimpleName() + "_" + ProcessHandle.current().pid(); + Path encodedConfigPath = Path.of(base + ".bin").toAbsolutePath(); + Path debugPath = Path.of(base + ".txt").toAbsolutePath(); command.add(encodedConfigPath.toString()); + command.add(debugPath.toString()); String quotedCommand = command.stream().map(e -> e.indexOf(' ') == -1 ? e : '\'' + e + '\'').collect(Collectors.joining(" ")); ProcessBuilder pb = new ProcessBuilder(command); @@ -178,8 +159,10 @@ public static Result from(Path javaHome, OptionValues options) { if (DEBUG) { System.out.printf("[%d] Executed: %s%n", p.pid(), quotedCommand); System.out.printf("[%d] Output saved in %s%n", p.pid(), encodedConfigPath); + System.out.printf("[%d] Debug output saved in %s%n", p.pid(), debugPath); } else { Files.deleteIfExists(encodedConfigPath); + Files.deleteIfExists(debugPath); } return new Result(encodedConfig, opens); } catch (IOException e) { diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetJNIConfig.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java similarity index 72% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetJNIConfig.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java index 92178a4c508a..8485c6a82822 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetJNIConfig.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,19 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot; - -import com.oracle.svm.core.OS; -import com.oracle.svm.core.util.UserError; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.ImageClassLoader; -import com.oracle.svm.util.LogUtils; -import com.oracle.svm.util.ModuleSupport; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotSignature; -import jdk.vm.ci.meta.JavaType; -import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; -import org.graalvm.nativeimage.hosted.RuntimeReflection; +package jdk.graal.compiler.libgraal; import java.io.BufferedReader; import java.io.IOException; @@ -44,6 +32,7 @@ import java.lang.reflect.Modifier; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -51,13 +40,21 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.util.SignatureUtil; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; +import org.graalvm.nativeimage.hosted.RuntimeReflection; + +import jdk.graal.compiler.debug.GraalError; /** * Registers the JNI configuration for libgraal by parsing the output of the * {@code -XX:JVMCILibDumpJNIConfig} VM option. */ -public final class GetJNIConfig implements AutoCloseable { +@Platforms(Platform.HOSTED_ONLY.class) +final class GetJNIConfig implements AutoCloseable { /** * VM command executed to read the JNI config. */ @@ -81,9 +78,9 @@ public final class GetJNIConfig implements AutoCloseable { int lineNo; - private GetJNIConfig(ClassLoader loader) { + private GetJNIConfig(ClassLoader loader, Path libgraalJavaHome) { this.loader = loader; - Path javaExe = getJavaExe(Path.of(System.getProperty("java.home"))); + Path javaExe = getJavaExe(libgraalJavaHome); configFilePath = Path.of("libgraal_jniconfig.txt"); String[] command = {javaExe.toFile().getAbsolutePath(), "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-XX:JVMCILibDumpJNIConfig=" + configFilePath}; @@ -94,34 +91,35 @@ private GetJNIConfig(ClassLoader loader) { try { p = pb.start(); } catch (IOException e) { - throw UserError.abort("Could not run command: %s%n%s", quotedCommand, e); + throw new GraalError(e, "Could not run command: %s", quotedCommand); } String nl = System.lineSeparator(); - String out = new BufferedReader(new InputStreamReader(p.getInputStream())) - .lines().collect(Collectors.joining(nl)); + String out = new BufferedReader(new InputStreamReader(p.getInputStream())).lines().collect(Collectors.joining(nl)); int exitValue; try { exitValue = p.waitFor(); } catch (InterruptedException e) { - throw UserError.abort("Interrupted waiting for command: %s%n%s", quotedCommand, out); + throw new GraalError(e, "Interrupted waiting for command: %s%n%s", quotedCommand, out); } if (exitValue != 0) { - throw UserError.abort("Command finished with exit value %d: %s%n%s", exitValue, quotedCommand, out); + throw new GraalError("Command finished with exit value %d: %s%n%s", exitValue, quotedCommand, out); } try { lines = Files.readAllLines(configFilePath); } catch (IOException e) { + Path cfp = configFilePath; configFilePath = null; - throw UserError.abort("Reading JNI config in %s dumped by command: %s%n%s", configFilePath, quotedCommand, out); + throw new GraalError("Reading JNI config in %s dumped by command: %s%n%s", cfp, quotedCommand, out); } } static Path getJavaExe(Path javaHome) { - Path javaExe = javaHome.resolve(Path.of("bin", OS.WINDOWS.isCurrent() ? "java.exe" : "java")); + boolean isWindows = GraalServices.getSavedProperty("os.name").contains("Windows"); + Path javaExe = javaHome.resolve(Path.of("bin", isWindows ? "java.exe" : "java")); if (!Files.isExecutable(javaExe)) { - throw UserError.abort("Java launcher %s does not exist or is not executable", javaExe); + throw new GraalError("Java launcher %s does not exist or is not executable", javaExe); } return javaExe; } @@ -133,24 +131,45 @@ public void close() { Files.delete(configFilePath); configFilePath = null; } catch (IOException e) { - LogUtils.warning("Could not delete %s: %s", configFilePath, e); + throw new GraalError(e, "Could not delete %s", configFilePath); } } } + public static Class forPrimitive(String name) { + return switch (name) { + case "Z", "boolean" -> boolean.class; + case "C", "char" -> char.class; + case "F", "float" -> float.class; + case "D", "double" -> double.class; + case "B", "byte" -> byte.class; + case "S", "short" -> short.class; + case "I", "int" -> int.class; + case "J", "long" -> long.class; + case "V", "void" -> void.class; + default -> null; + }; + } + private Class findClass(String name) { String internalName = name; if (name.startsWith("L") && name.endsWith(";")) { internalName = name.substring(1, name.length() - 1); } - var primitive = ImageClassLoader.forPrimitive(internalName); + var primitive = forPrimitive(internalName); if (primitive != null) { return primitive; } try { return Class.forName(internalName, false, loader); } catch (ClassNotFoundException e) { - throw VMError.shouldNotReachHere("Cannot find class during LibGraal JNIConfiguration registration", e); + String externalName = internalName.replace('/', '.'); + try { + return Class.forName(externalName, false, loader); + } catch (ClassNotFoundException e3) { + // ignore + } + throw new GraalError(e, "Cannot find class %s during LibGraal JNIConfiguration registration", name); } } @@ -160,12 +179,12 @@ private void check(boolean condition, String format, Object... args) { } } - private UserError.UserException error(String format, Object... args) { + private GraalError error(String format, Object... args) { Path path = configFilePath; configFilePath = null; // prevent deletion - String errorMessage = String.format(format, args); + String errorMessage = format.formatted(args); String errorLine = lines.get(lineNo - 1); - throw UserError.abort("Line %d of %s: %s%n%s%n%s generated by command: %s", + throw new GraalError("Line %d of %s: %s%n%s%n%s generated by command: %s", lineNo, path.toAbsolutePath(), errorMessage, errorLine, path, quotedCommand); } @@ -177,11 +196,8 @@ private UserError.UserException error(String format, Object... args) { * @param loader used to resolve type names in the config */ @SuppressWarnings("try") - public static void register(ClassLoader loader) { - // Export all JVMCI packages to this class - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, GetJNIConfig.class, false, "jdk.internal.vm.ci"); - - try (GetJNIConfig source = new GetJNIConfig(loader)) { + public static void register(ClassLoader loader, Path libgraalJavaHome) { + try (GetJNIConfig source = new GetJNIConfig(loader, libgraalJavaHome)) { Map> classes = new HashMap<>(); for (String line : source.lines) { source.lineNo++; @@ -191,7 +207,6 @@ public static void register(ClassLoader loader) { Class clazz = classes.get(className); if (clazz == null) { clazz = source.findClass(className); - assert clazz.getClassLoader() == null || clazz.getClassLoader() == loader; RuntimeJNIAccess.register(clazz); RuntimeJNIAccess.register(Array.newInstance(clazz, 0).getClass()); classes.put(className, clazz); @@ -213,13 +228,13 @@ public static void register(ClassLoader loader) { case "method": { source.check(tokens.length == 4, "Expected 4 tokens for a method"); String methodName = tokens[2]; - HotSpotJVMCIRuntime runtime = runtime(); String signature = tokens[3]; - HotSpotSignature descriptor = new HotSpotSignature(runtime, signature); - Class[] parameters = Stream.of(descriptor.toParameterTypes(null))// - .map(JavaType::toClassName).map(source::findClass)// + ArrayList buffer = new ArrayList<>(); + SignatureUtil.parseSignature(signature, buffer); + Class[] parameters = buffer.stream()// + .map(source::findClass)// .toList()// - .toArray(new Class[descriptor.getParameterCount(false)]); + .toArray(new Class[0]); assert Arrays.stream(parameters).allMatch(pclazz -> pclazz.getClassLoader() == null || pclazz.getClassLoader() == loader); try { if ("".equals(methodName)) { @@ -235,9 +250,9 @@ public static void register(ClassLoader loader) { RuntimeJNIAccess.register(clazz.getDeclaredMethod(methodName, parameters)); } } catch (NoSuchMethodException e) { - throw source.error("Method %s.%s%s not found: %s", clazz.getTypeName(), methodName, descriptor, e); + throw source.error("Method %s.%s%s not found: %s", clazz.getTypeName(), methodName, signature, e); } catch (NoClassDefFoundError e) { - throw source.error("Could not register method %s.%s%s: %s", clazz.getTypeName(), methodName, descriptor, e); + throw source.error("Could not register method %s.%s%s: %s", clazz.getTypeName(), methodName, signature, e); } break; } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/JDKLatest.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/JDKLatest.java new file mode 100644 index 000000000000..cef8bbe6a07e --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/JDKLatest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import java.util.function.BooleanSupplier; + +import jdk.graal.compiler.serviceprovider.JavaVersionUtil; + +/** + * Denotes the latest supported JDK version. It corresponds to the highest key in the + * {@code JVMCI_MIN_VERSIONS} map in {@link jdk.graal.compiler.hotspot.JVMCIVersionCheck}. + */ +public class JDKLatest implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return JavaVersionUtil.JAVA_SPEC > 21; + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.java new file mode 100644 index 000000000000..d8ad32e8bdb4 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import org.graalvm.nativeimage.hosted.Feature.DuringSetupAccess; + +/** + * The image runtime class loader that {@linkplain DuringSetupAccess#registerObjectReplacer + * replaces} the build-time instance of the {@link org.graalvm.nativeimage.libgraal.LibGraalLoader}. + */ +final class LibGraalClassLoader extends ClassLoader { + + LibGraalClassLoader(String name) { + super(name, null); + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java new file mode 100644 index 000000000000..2636fed1451f --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Map; + +import jdk.graal.compiler.debug.GlobalMetrics; +import jdk.graal.compiler.hotspot.CompilationContext; +import jdk.graal.compiler.hotspot.CompilationTask; +import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; +import jdk.graal.compiler.hotspot.HotSpotGraalRuntime; +import jdk.graal.compiler.hotspot.HotSpotGraalServices; +import jdk.graal.compiler.hotspot.ProfileReplaySupport; +import jdk.graal.compiler.options.OptionDescriptors; +import jdk.graal.compiler.options.OptionKey; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.options.OptionsParser; +import jdk.graal.compiler.util.OptionsEncoder; +import jdk.graal.compiler.word.Word; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotInstalledCode; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.runtime.JVMCICompiler; +import org.graalvm.collections.EconomicMap; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNIExceptionWrapper; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateThreadContext; +import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.word.PointerBase; + +import jdk.internal.misc.Unsafe; + +import static jdk.graal.compiler.serviceprovider.GraalServices.getCurrentThreadAllocatedBytes; +import static jdk.graal.compiler.serviceprovider.GraalServices.isThreadAllocatedMemorySupported; + +/** + * Encapsulates {@link CEntryPoint} implementations. + */ +final class LibGraalEntryPoints { + + @Platforms(Platform.HOSTED_ONLY.class) + private LibGraalEntryPoints() { + } + + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + private record CachedOptions(OptionValues options, long hash) { + } + + private static final ThreadLocal CACHED_OPTIONS_THREAD_LOCAL = new ThreadLocal<>(); + + private static OptionValues decodeOptions(long address, int size, int hash) { + CachedOptions options = CACHED_OPTIONS_THREAD_LOCAL.get(); + if (options == null || options.hash != hash) { + byte[] buffer = new byte[size]; + UNSAFE.copyMemory(null, address, buffer, Unsafe.ARRAY_BYTE_BASE_OFFSET, size); + int actualHash = Arrays.hashCode(buffer); + if (actualHash != hash) { + throw new IllegalArgumentException(actualHash + " != " + hash); + } + Map srcMap = OptionsEncoder.decode(buffer); + final EconomicMap, Object> dstMap = OptionValues.newOptionMap(); + final Iterable loader = OptionsParser.getOptionsLoader(); + for (Map.Entry e : srcMap.entrySet()) { + final String optionName = e.getKey(); + final Object optionValue = e.getValue(); + OptionsParser.parseOption(optionName, optionValue, dstMap, loader); + } + + options = new CachedOptions(new OptionValues(dstMap), hash); + CACHED_OPTIONS_THREAD_LOCAL.set(options); + } + return options.options; + } + + /** + * The implementation of + * {@code jdk.graal.compiler.hotspot.test.LibGraalCompilationDriver#compileMethodInLibgraal}. + * + * @param methodHandle the method to be compiled. This is a handle to a + * {@code HotSpotResolvedJavaMethod} in HotSpot's heap. A value of 0L can be passed + * to use this method for the side effect of initializing a + * {@code HotSpotGraalCompiler} instance without doing any compilation. + * @param useProfilingInfo specifies if profiling info should be used during the compilation + * @param installAsDefault specifies if the compiled code should be installed for the + * {@code Method*} associated with {@code methodHandle} + * @param printMetrics specifies if global metrics should be printed and reset + * @param optionsAddress native byte buffer storing a serialized {@code OptionValues} object + * @param optionsSize the number of bytes in the buffer + * @param optionsHash hash code of bytes in the buffer (computed with + * {@link Arrays#hashCode(byte[])}) + * @param stackTraceAddress a native buffer in which a serialized stack trace can be returned. + * The caller will only read from this buffer if this method returns 0. A returned + * serialized stack trace is returned in this buffer with the following format: + * + *
+     *               struct {
+     *                   int   length;
+     *                   byte  data[length]; // Bytes from a stack trace printed to a ByteArrayOutputStream.
+     *               }
+     *            
+ * + * where {@code length} is truncated to {@code stackTraceCapacity - 4} if necessary + * + * @param stackTraceCapacity the size of the stack trace buffer + * @param timeAndMemBufferAddress 16-byte native buffer to store result of time and memory + * measurements of the compilation + * @param profilePathBufferAddress native buffer containing a 0-terminated C string representing + * {@code Options#LoadProfiles} path. + * @return a handle to a {@code InstalledCode} in HotSpot's heap or 0 if compilation failed + */ + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_test_LibGraalCompilationDriver_compileMethodInLibgraal", include = LibGraalFeature.IsEnabled.class) + private static long compileMethod(JNIEnv jniEnv, + PointerBase jclass, + @IsolateThreadContext long isolateThreadAddress, + long methodHandle, + boolean useProfilingInfo, + boolean installAsDefault, + boolean printMetrics, + boolean eagerResolving, + long optionsAddress, + int optionsSize, + int optionsHash, + long stackTraceAddress, + int stackTraceCapacity, + long timeAndMemBufferAddress, + long profilePathBufferAddress) { + try (JNIMethodScope jniScope = new JNIMethodScope("compileMethod", jniEnv)) { + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); + if (methodHandle == 0L) { + return 0L; + } + + int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; + HotSpotResolvedJavaMethod method = runtime.unhand(HotSpotResolvedJavaMethod.class, methodHandle); + HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); + try (CompilationContext ignored = HotSpotGraalServices.openLocalCompilationContext(request)) { + CompilationTask task = new CompilationTask(runtime, compiler, request, useProfilingInfo, false, false, eagerResolving, installAsDefault); + long allocatedBytesBefore = 0; + long timeBefore = 0; + if (timeAndMemBufferAddress != 0) { + allocatedBytesBefore = isThreadAllocatedMemorySupported() ? getCurrentThreadAllocatedBytes() : -1; + timeBefore = System.nanoTime(); + } + OptionValues options = decodeOptions(optionsAddress, optionsSize, optionsHash); + if (profilePathBufferAddress > 0) { + String profileLoadPath = CTypeConversion.toJavaString(Word.pointer(profilePathBufferAddress)); + options = new OptionValues(options, ProfileReplaySupport.Options.LoadProfiles, profileLoadPath); + } + task.runCompilation(options); + if (timeAndMemBufferAddress != 0) { + long allocatedBytesAfter = allocatedBytesBefore == -1 ? -1 : getCurrentThreadAllocatedBytes(); + long bytesAllocated = allocatedBytesAfter - allocatedBytesBefore; + long timeAfter = System.nanoTime(); + long timeSpent = timeAfter - timeBefore; + Unsafe.getUnsafe().putLong(timeAndMemBufferAddress, bytesAllocated); + Unsafe.getUnsafe().putLong(timeAndMemBufferAddress + 8, timeSpent); + } + HotSpotInstalledCode installedCode = task.getInstalledCode(); + if (printMetrics) { + GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues(); + metricValues.print(options); + metricValues.clear(); + } + return runtime.translate(installedCode); + } + } catch (Throwable t) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + t.printStackTrace(new PrintStream(baos)); + byte[] stackTrace = baos.toByteArray(); + int length = Math.min(stackTraceCapacity - Integer.BYTES, stackTrace.length); + Unsafe.getUnsafe().putInt(stackTraceAddress, length); + Unsafe.getUnsafe().copyMemory(stackTrace, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, stackTraceAddress + Integer.BYTES, length); + return 0L; + } finally { + /* + * libgraal doesn't use a dedicated reference handler thread, so we trigger the + * reference handling manually when a compilation finishes. + */ + LibGraalSupportImpl.doReferenceHandling(); + } + } + + @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_test_LibGraalCompilerTest_hashConstantOopFields", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + private static long hashConstantOopFields(JNIEnv jniEnv, + PointerBase jclass, + @IsolateThreadContext long isolateThreadAddress, + long typeHandle, + boolean useScope, + int iterations, + int oopsPerIteration, + boolean verbose) { + try (JNIMethodScope scope = new JNIMethodScope("hashConstantOopFields", jniEnv)) { + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + JVMCIBackend backend = runtime.getHostJVMCIBackend(); + ConstantReflectionProvider constantReflection = backend.getConstantReflection(); + HotSpotResolvedJavaType type = runtime.unhand(HotSpotResolvedJavaType.class, typeHandle); + ResolvedJavaField[] staticFields = type.getStaticFields(); + JavaConstant receiver = null; + long hash = 13; + + Object scopeDescription = "TestingOopHandles"; + + int remainingIterations = iterations; + while (remainingIterations-- > 0) { + ResolvedJavaField lastReadField = null; + try (CompilationContext scope1 = useScope ? HotSpotGraalServices.openLocalCompilationContext(scopeDescription) : null) { + if (verbose && useScope) { + System.out.println("Opened " + scopeDescription); + } + int remainingOops = oopsPerIteration; + while (remainingOops-- > 0) { + for (ResolvedJavaField field : staticFields) { + if (field.getType().getJavaKind() == JavaKind.Object) { + JavaConstant value = constantReflection.readFieldValue(field, receiver); + if (value != null) { + lastReadField = field; + hash = hash ^ value.hashCode(); + } + } + } + } + } + if (!useScope) { + System.gc(); + if (verbose) { + System.out.println("calling reference handling"); + } + LibGraalSupportImpl.doReferenceHandling(); + if (verbose) { + System.out.println("called reference handling"); + } + // Need one more remote oop creation to trigger releasing + // of remote oops that were wrapped in weakly reachable + // IndirectHotSpotObjectConstantImpl objects just collected. + constantReflection.readFieldValue(lastReadField, receiver); + } else if (verbose) { + System.out.println(" Closed " + scopeDescription); + } + } + return hash; + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(jniEnv, t); + return 0; + } + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java new file mode 100644 index 000000000000..5484eb3b7b76 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.module.ModuleDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.jniutils.NativeBridgeSupport; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.FieldValueTransformer; +import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; +import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; + +import jdk.graal.compiler.core.common.Fields; +import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.Edges; +import jdk.graal.compiler.graph.NodeClass; +import jdk.graal.compiler.hotspot.EncodedSnippets; +import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; +import jdk.graal.compiler.libgraal.truffle.LibGraalTruffleHostEnvironmentLookup; +import jdk.graal.compiler.options.OptionDescriptor; +import jdk.graal.compiler.options.OptionKey; +import jdk.graal.compiler.options.OptionsParser; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.truffle.host.TruffleHostEnvironment; +import jdk.graal.compiler.util.ObjectCopier; +import jdk.internal.module.Modules; +import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotModifiers; +import jdk.vm.ci.services.JVMCIServiceLocator; + +/** + * This feature builds the libgraal shared library (e.g., libjvmcicompiler.so on linux). + */ +@Platforms(Platform.HOSTED_ONLY.class) +public final class LibGraalFeature implements Feature { + + /** + * Looks up a class in the libgraal class loader. + * + * @throws Error if the lookup fails + */ + public static Class lookupClass(String className) { + try { + return Class.forName(className, false, LibGraalFeature.class.getClassLoader()); + } catch (ClassNotFoundException ex) { + throw new GraalError(ex); + } + } + + /** + * Looks up a field via reflection and makes it accessible for reading. + * + * @throws Error if the operation fails + */ + public static Field lookupField(Class declaringClass, String fieldName) { + try { + Field result = declaringClass.getDeclaredField(fieldName); + Modules.addOpensToAllUnnamed(declaringClass.getModule(), declaringClass.getPackageName()); + result.setAccessible(true); + return result; + } catch (ReflectiveOperationException ex) { + throw new GraalError(ex); + } + } + + public static final class IsEnabled implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + Class clazz = LibGraalFeature.class; + return ImageSingletons.contains(clazz); + } + } + + /** + * See javadoc for {@code jdk.graal.compiler.libgraal.loader.HostedLibGraalClassLoader}. + */ + private static Path readLibgraalJavaHome(ClassLoader cl) { + try (InputStream in = cl.getResourceAsStream("META-INF/libgraal.java.home")) { + if (in == null) { + throw new GraalError(cl.getClass().getName() + " does not support META-INF/libgraal.java.home protocol (see javadoc of HostedLibGraalClassLoader)"); + } + return Path.of(new String(in.readAllBytes())); + } catch (IOException e) { + throw new GraalError(e); + } + } + + private final LibGraalLoader libgraalLoader = (LibGraalLoader) getClass().getClassLoader(); + private final Path libgraalJavaHome = readLibgraalJavaHome(getClass().getClassLoader()); + + private BeforeAnalysisAccess beforeAnalysisAccess; + private BeforeCompilationAccess beforeCompilationAccess; + private OptionCollector optionCollector; + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + ImageSingletons.add(NativeBridgeSupport.class, new LibGraalNativeBridgeSupport()); + + // All qualified exports to libgraal modules need to be further exported to + // ALL-UNNAMED so that access is also possible when the libgraal classes + // are loaded via the libgraal loader into unnamed modules. + Set libgraalModules = Set.copyOf(libgraalLoader.getClassModuleMap().values()); + for (Module module : ModuleLayer.boot().modules()) { + Set exports = module.getDescriptor().exports(); + for (ModuleDescriptor.Exports e : exports) { + if (e.targets().stream().anyMatch(libgraalModules::contains)) { + Modules.addExportsToAllUnnamed(module, e.source()); + } + } + } + } + + @Override + public void duringSetup(DuringSetupAccess access) { + optionCollector = new OptionCollector(); + + /* + * Replace HostedLibGraalClassLoader with a basic class loader at runtime that cuts out the + * parent class loader (i.e., NativeImageClassLoader) and is guaranteed not to make any + * additional types/methods/fields accidentally reachable. + */ + String loaderName = ((ClassLoader) libgraalLoader).getName(); + LibGraalClassLoader runtimeLibgraalLoader = new LibGraalClassLoader(loaderName); + access.registerObjectReplacer(obj -> obj == libgraalLoader ? runtimeLibgraalLoader : obj); + + // Register reachability handler used to initialize OptionsParser.libgraalOptions. + access.registerObjectReachabilityHandler(optionCollector::accept, OptionKey.class); + + // Register reachability handler that marks the fields that are accessed via unsafe. + access.registerObjectReachabilityHandler(fields -> { + for (int i = 0; i < fields.getOffsets().length; i++) { + Field field = fields.getField(i); + beforeAnalysisAccess.registerAsUnsafeAccessed(field); + } + }, Fields.class); + + // Register reachability handler that marks NodeClass subclasses as unsafe allocated + // (see jdk.graal.compiler.graph.NodeClass.allocateInstance). + access.registerObjectReachabilityHandler(nodeClass -> { + Class clazz = nodeClass.getClazz(); + if (!Modifier.isAbstract(clazz.getModifiers())) { + /* Support for NodeClass.allocateInstance. */ + beforeAnalysisAccess.registerAsUnsafeAllocated(clazz); + } + }, NodeClass.class); + + // Register the fields/methods/classes accessed via JNI. + GetJNIConfig.register((ClassLoader) libgraalLoader, libgraalJavaHome); + } + + /** + * Collects all instances of the LibGraalLoader loaded {@link OptionKey} class reached by the + * static analysis and uses them to initialize {@link OptionsParser#libgraalOptions}. + */ + private final class OptionCollector implements Consumer> { + private final Set> options = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + private boolean sealed; + + @Override + public void accept(OptionKey option) { + if (sealed) { + GraalError.guarantee(options.contains(option), "All options must have been discovered during static analysis: %s", option); + } else { + options.add(option); + } + } + + void afterAnalysis(AfterAnalysisAccess access) { + sealed = true; + Map modules = libgraalLoader.getClassModuleMap(); + for (OptionKey option : options) { + OptionDescriptor descriptor = option.getDescriptor(); + if (descriptor.isServiceLoaded()) { + GraalError.guarantee(access.isReachable(option.getClass()), "%s", option.getClass()); + GraalError.guarantee(access.isReachable(descriptor.getClass()), "%s", descriptor.getClass()); + + String name = option.getName(); + OptionsParser.libgraalOptions.descriptors().put(name, descriptor); + + String module = modules.get(descriptor.getDeclaringClass().getName()); + if (module.contains("enterprise")) { + OptionsParser.libgraalOptions.enterpriseOptions().add(name); + } + } + } + } + } + + /** + * Transformer for {@code Fields.offsets} and {@code Edges.iterationMask} which need to be + * recomputed to use SVM field offsets instead of HotSpot field offsets. + */ + class FieldOffsetsTransformer implements FieldValueTransformer { + /** + * Map from {@link Fields} objects to a (newOffsets, newIterationMask) tuple represented as + * a {@link java.util.Map.Entry} value. + */ + private final Map> replacements = new IdentityHashMap<>(); + + final Field fieldsOffsetsField; + final Field edgesIterationMaskField; + + FieldOffsetsTransformer() { + fieldsOffsetsField = lookupField(Fields.class, "offsets"); + edgesIterationMaskField = lookupField(Edges.class, "iterationMask"); + } + + void register(BeforeAnalysisAccess access) { + access.registerFieldValueTransformer(fieldsOffsetsField, this); + access.registerFieldValueTransformer(edgesIterationMaskField, this); + } + + @Override + public boolean isAvailable() { + return beforeCompilationAccess != null; + } + + @Override + public Object transform(Object receiver, Object originalValue) { + Map.Entry repl = getReplacement(receiver); + if (originalValue instanceof long[]) { + return repl.getKey(); + } + return repl.getValue(); + } + + private Map.Entry getReplacement(Object receiver) { + synchronized (replacements) { + return replacements.computeIfAbsent(receiver, this::computeReplacement); + } + } + + private Map.Entry computeReplacement(Object receiver) { + Fields fields = (Fields) receiver; + return fields.recomputeOffsetsAndIterationMask(beforeCompilationAccess::objectFieldOffset); + } + } + + @SuppressWarnings("unchecked") + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + beforeAnalysisAccess = access; + new FieldOffsetsTransformer().register(access); + + /* Contains static fields that depend on HotSpotJVMCIRuntime */ + RuntimeClassInitialization.initializeAtRunTime(HotSpotModifiers.class); + RuntimeClassInitialization.initializeAtRunTime(lookupClass("jdk.vm.ci.hotspot.HotSpotCompiledCodeStream")); + RuntimeClassInitialization.initializeAtRunTime(lookupClass("jdk.vm.ci.hotspot.HotSpotCompiledCodeStream$Tag")); + + /* Needed for runtime calls to BoxingSnippets.Templates.getCacheClass(JavaKind) */ + RuntimeReflection.registerAllDeclaredClasses(Character.class); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Character$CharacterCache"), "cache")); + RuntimeReflection.registerAllDeclaredClasses(Byte.class); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Byte$ByteCache"), "cache")); + RuntimeReflection.registerAllDeclaredClasses(Short.class); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Short$ShortCache"), "cache")); + RuntimeReflection.registerAllDeclaredClasses(Integer.class); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Integer$IntegerCache"), "cache")); + RuntimeReflection.registerAllDeclaredClasses(Long.class); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Long$LongCache"), "cache")); + + doLegacyJVMCIInitialization(); + + GetCompilerConfig.Result configResult = GetCompilerConfig.from(libgraalJavaHome); + for (var e : configResult.opens().entrySet()) { + Module module = ModuleLayer.boot().findModule(e.getKey()).orElseThrow(); + for (String source : e.getValue()) { + Modules.addOpensToAllUnnamed(module, source); + } + } + + EconomicMap libgraalObjects = (EconomicMap) ObjectCopier.decode(configResult.encodedConfig(), (ClassLoader) libgraalLoader); + EncodedSnippets encodedSnippets = (EncodedSnippets) libgraalObjects.get("encodedSnippets"); + + // Mark all the Node classes as allocated so they are available during graph decoding. + for (NodeClass nodeClass : encodedSnippets.getSnippetNodeClasses()) { + access.registerAsInHeap(nodeClass.getClazz()); + } + HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); + + List foreignCallSignatures = (List) libgraalObjects.get("foreignCallSignatures"); + HotSpotForeignCallLinkage.Stubs.initStubs(foreignCallSignatures); + + TruffleHostEnvironment.overrideLookup(new LibGraalTruffleHostEnvironmentLookup()); + } + + /** + * Initialization of JVMCI code that needs to be done for JDK versions that do not include + * JDK-8346781. + */ + private void doLegacyJVMCIInitialization() { + if (!BeforeJDK8346781.VALUE) { + return; + } + try { + String rawArch = GraalServices.getSavedProperty("os.arch"); + String arch = switch (rawArch) { + case "x86_64", "amd64" -> "AMD64"; + case "aarch64" -> "aarch64"; + case "riscv64" -> "riscv64"; + default -> throw new GraalError("Unknown or unsupported arch: %s", rawArch); + }; + + ClassLoader cl = (ClassLoader) libgraalLoader; + Field cachedHotSpotJVMCIBackendFactoriesField = ObjectCopier.getField(HotSpotJVMCIRuntime.class, "cachedHotSpotJVMCIBackendFactories"); + GraalError.guarantee(cachedHotSpotJVMCIBackendFactoriesField.get(null) == null, "Expect cachedHotSpotJVMCIBackendFactories to be null"); + ServiceLoader load = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, cl); + List backendFactories = load.stream()// + .map(ServiceLoader.Provider::get)// + .filter(s -> s.getArchitecture().equals(arch))// + .toList(); + cachedHotSpotJVMCIBackendFactoriesField.set(null, backendFactories); + GraalError.guarantee(backendFactories.size() == 1, "%s", backendFactories); + + var jvmciServiceLocatorCachedLocatorsField = ObjectCopier.getField(JVMCIServiceLocator.class, "cachedLocators"); + GraalError.guarantee(jvmciServiceLocatorCachedLocatorsField.get(null) == null, "Expect cachedLocators to be null"); + Iterable serviceLocators = ServiceLoader.load(JVMCIServiceLocator.class, cl); + List cachedLocators = new ArrayList<>(); + serviceLocators.forEach(cachedLocators::add); + jvmciServiceLocatorCachedLocatorsField.set(null, cachedLocators); + } catch (Throwable e) { + throw new GraalError(e); + } + } + + @Override + public void afterAnalysis(AfterAnalysisAccess access) { + optionCollector.afterAnalysis(access); + } + + @Override + public void beforeCompilation(BeforeCompilationAccess access) { + beforeCompilationAccess = access; + } +} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/LibGraalJNIMethodScope.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java similarity index 98% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/LibGraalJNIMethodScope.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java index 7b9271205fa7..47ad9f5fd524 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/LibGraalJNIMethodScope.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot; +package jdk.graal.compiler.libgraal; import org.graalvm.jniutils.JNI.JNIEnv; import org.graalvm.jniutils.JNIMethodScope; diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalNativeBridgeSupport.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java similarity index 85% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalNativeBridgeSupport.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java index b1167d39a63a..70bc289a54dd 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalNativeBridgeSupport.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,16 +22,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot.libgraal; +package jdk.graal.compiler.libgraal; import java.util.concurrent.atomic.AtomicInteger; +import jdk.graal.compiler.debug.TTY; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.serviceprovider.IsolateUtil; import org.graalvm.jniutils.JNIMethodScope; import org.graalvm.jniutils.NativeBridgeSupport; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.IsolateSupport; - public final class LibGraalNativeBridgeSupport implements NativeBridgeSupport { private static final String JNI_LIBGRAAL_TRACE_LEVEL_PROPERTY_NAME = "JNI_LIBGRAAL_TRACE_LEVEL"; @@ -63,14 +63,14 @@ public void trace(String message) { inTrace.set(true); try { StringBuilder sb = new StringBuilder(); - long isolateID = ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); + long isolateID = IsolateUtil.getIsolateID(); sb.append('[').append(isolateID).append(':').append(Thread.currentThread().getName()).append(']'); JNIMethodScope scope = JNIMethodScope.scopeOrNull(); if (scope != null) { sb.append(" ".repeat(2 + (scope.depth() * 2))); } sb.append(message); - LibGraalEntryPoints.ttyPrintf("%s%n", sb); + TTY.printf("%s%n", sb); } finally { inTrace.remove(); } @@ -80,12 +80,12 @@ public void trace(String message) { private int traceLevel() { int res = traceLevel.get(); if (res == UNINITIALIZED_TRACE_LEVEL) { - String var = LibGraalEntryPoints.getSavedProperty(JNI_LIBGRAAL_TRACE_LEVEL_PROPERTY_NAME); + String var = GraalServices.getSavedProperty(JNI_LIBGRAAL_TRACE_LEVEL_PROPERTY_NAME); if (var != null) { try { res = Integer.parseInt(var); } catch (NumberFormatException e) { - LibGraalEntryPoints.ttyPrintf("Invalid value for %s: %s%n", JNI_LIBGRAAL_TRACE_LEVEL_PROPERTY_NAME, e); + TTY.printf("Invalid value for %s: %s%n", JNI_LIBGRAAL_TRACE_LEVEL_PROPERTY_NAME, e); res = 0; } } else { diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java new file mode 100644 index 000000000000..6f6223353c0e --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; + +class LibGraalSubstitutions { + + @TargetClass(className = "jdk.vm.ci.services.Services", onlyWith = LibGraalFeature.IsEnabled.class) + static final class Target_jdk_vm_ci_services_Services { + /** + * Ensures field returns false if seen by the analysis. + */ + // Checkstyle: stop + @Alias // + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// + @TargetElement(onlyWith = BeforeJDK8346781.class)// + public static boolean IS_BUILDING_NATIVE_IMAGE = false; + // Checkstyle: resume + + /* + * Static final boolean field Services.IS_IN_NATIVE_IMAGE is used in many places in the + * JVMCI codebase to switch between the different implementations needed for regular use (a + * built-in module jdk.graal.compiler in the JVM) or as part of libgraal. + */ + // Checkstyle: stop + @Alias // + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// + public static boolean IS_IN_NATIVE_IMAGE = true; + // Checkstyle: resume + } + + @TargetClass(className = "jdk.vm.ci.hotspot.Cleaner", onlyWith = LibGraalFeature.IsEnabled.class) + static final class Target_jdk_vm_ci_hotspot_Cleaner { + + /* + * Make package-private clean() accessible so that it can be called from + * LibGraalEntryPoints.doReferenceHandling(). + */ + @Alias + public static native void clean(); + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSupportImpl.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSupportImpl.java new file mode 100644 index 000000000000..ff533e212736 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSupportImpl.java @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal; + +import java.io.Closeable; +import java.io.PrintStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import jdk.graal.compiler.options.OptionValues; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.MapCursor; +import org.graalvm.jniutils.JNI; +import org.graalvm.jniutils.JNIExceptionWrapper; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.nativeimage.CurrentIsolate; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.RuntimeOptions; +import org.graalvm.nativeimage.StackValue; +import org.graalvm.nativeimage.VMRuntime; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; +import org.graalvm.nativeimage.libgraal.LibGraalRuntime; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; + +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.libgraal.truffle.HSTruffleCompilerRuntime; +import jdk.graal.compiler.serviceprovider.JavaVersionUtil; +import jdk.graal.compiler.word.Word; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.hotspot.HotSpotVMConfigStore; + +/** + * Implementation of {@link LibGraalSupport} that is only loaded by the libgraal class loader when + * building libgraal. Only in the libgraal class loader context as libgraal build-time as well as at + * libgraal runtime is the {@link LibGraalSupport#INSTANCE} non-null. + */ +public final class LibGraalSupportImpl implements LibGraalSupport { + + private final LibGraalLoader libGraalLoader = (LibGraalLoader) getClass().getClassLoader(); + + private static HSTruffleCompilerRuntime truffleRuntime; + + public static void registerTruffleCompilerRuntime(HSTruffleCompilerRuntime runtime) { + GraalError.guarantee(truffleRuntime == null, "cannot register more than one Truffle runtime"); + truffleRuntime = runtime; + } + + @Override + public AutoCloseable openCompilationRequestScope() { + return new LibGraalCompilationRequestScope(); + } + + @Platforms(Platform.HOSTED_ONLY.class) + @Override + public Supplier createGlobal(long initialValue) { + return GlobalData.createGlobal(initialValue); + } + + /** + * Performs the following actions around a libgraal compilation: + *
    + *
  • before: opens a JNIMethodScope to allow Graal compilations of Truffle host methods to + * call methods on the TruffleCompilerRuntime.
  • + *
  • after: closes the above JNIMethodScope
  • + *
  • after: triggers GC weak reference processing as SVM does not use a separate thread for + * this in libgraal
  • + *
+ */ + static class LibGraalCompilationRequestScope implements AutoCloseable { + final JNIMethodScope scope; + + LibGraalCompilationRequestScope() { + JNI.JNIEnv env = Word.unsigned(getJNIEnv()); + /* + * This scope is required to allow Graal compilations of host methods to call methods in + * the TruffleCompilerRuntime. This is, for example, required to find out about + * Truffle-specific method annotations. + */ + scope = LibGraalJNIMethodScope.open("", env, false); + } + + @Override + public void close() { + try { + if (scope != null) { + scope.close(); + } + } finally { + /* + * libgraal doesn't use a dedicated reference handler thread, so trigger the + * reference handling manually when a compilation finishes. + */ + LibGraalSupportImpl.doReferenceHandling(); + } + } + } + + private static long jniEnvironmentOffset = Integer.MAX_VALUE; + + private static long getJniEnvironmentOffset() { + if (jniEnvironmentOffset == Integer.MAX_VALUE) { + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); + HotSpotVMConfigAccess config = new HotSpotVMConfigAccess(store); + jniEnvironmentOffset = config.getFieldOffset("JavaThread::_jni_environment", Integer.class, "JNIEnv"); + } + return jniEnvironmentOffset; + } + + /** + * Gets the JNIEnv value for the current HotSpot thread. + */ + private static long getJNIEnv() { + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + long offset = getJniEnvironmentOffset(); + long javaThreadAddr = jvmciRuntime.getCurrentJavaThread(); + return javaThreadAddr + offset; + } + + @Platforms(Platform.HOSTED_ONLY.class) + @Override + public Map getClassModuleMap() { + return libGraalLoader.getClassModuleMap(); + } + + @Override + public void processReferences() { + LibGraalRuntime.processReferences(); + } + + @Override + public long getIsolateAddress() { + return CurrentIsolate.getIsolate().rawValue(); + } + + @Override + public long getIsolateID() { + return LibGraalRuntime.getIsolateID(); + } + + /** + * The set of libgraal options seen on the command line. + */ + static EconomicSet explicitOptions = EconomicSet.create(); + + @Override + public void notifyOptions(EconomicMap settings) { + MapCursor cursor = settings.getEntries(); + while (cursor.advance()) { + String name = cursor.getKey(); + String stringValue = cursor.getValue(); + Object value; + if (name.startsWith("X") && stringValue.isEmpty()) { + name = name.substring(1); + value = stringValue; + } else { + RuntimeOptions.Descriptor desc = RuntimeOptions.getDescriptor(name); + if (desc == null) { + throw new IllegalArgumentException("Could not find option " + name); + } + value = desc.convertValue(stringValue); + explicitOptions.add(name); + } + try { + RuntimeOptions.set(name, value); + } catch (RuntimeException ex) { + throw new IllegalArgumentException(ex); + } + } + } + + @Override + public void printOptions(PrintStream out, String namePrefix) { + Comparator comparator = Comparator.comparing(RuntimeOptions.Descriptor::name); + RuntimeOptions.listDescriptors().stream().sorted(comparator).forEach(d -> { + String assign = explicitOptions.contains(d.name()) ? ":=" : "="; + OptionValues.printHelp(out, namePrefix, + d.name(), + RuntimeOptions.get(d.name()), + d.valueType(), + assign, + "[community edition]", + d.help(), + List.of()); + }); + } + + @Override + public void initialize() { + VMRuntime.initialize(); + } + + @Override + @SuppressWarnings("try") + public void shutdown(String callbackClassName, String callbackMethodName) { + try (CanCallJavaScope ignore = CanCallJavaScope.open()) { + if (callbackClassName != null) { + JNI.JNIEnv env = Word.unsigned(getJNIEnv()); + JNI.JClass cbClass = JNIUtil.findClass(env, JNIUtil.getSystemClassLoader(env), + JNIUtil.getBinaryName(callbackClassName), true); + JNI.JMethodID cbMethod = JNIUtil.findMethod(env, cbClass, true, callbackMethodName, "()V"); + env.getFunctions().getCallStaticVoidMethodA().call(env, cbClass, cbMethod, StackValue.get(0)); + JNIExceptionWrapper.wrapAndThrowPendingJNIException(env); + } + if (truffleRuntime != null) { + JNI.JNIEnv env = Word.unsigned(getJNIEnv()); + truffleRuntime.notifyShutdown(env); + } + } + VMRuntime.shutdown(); + + } + + private static final class CanCallJavaScope implements Closeable { + + private static final MethodHandle CAN_CALL_JAVA_SCOPE = findCompilerThreadCanCallJavaScopeConstructor(); + + private static MethodHandle findCompilerThreadCanCallJavaScopeConstructor() { + try { + return MethodHandles.lookup().findConstructor(Class.forName("jdk.vm.ci.hotspot.CompilerThreadCanCallJavaScope"), MethodType.methodType(void.class, boolean.class)); + } catch (ReflectiveOperationException e) { + if (JavaVersionUtil.JAVA_SPEC != 21) { + throw new InternalError(e); + } + } + return null; + } + + private final AutoCloseable impl; + + private CanCallJavaScope() { + try { + impl = (AutoCloseable) CAN_CALL_JAVA_SCOPE.invoke(true); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable throwable) { + throw new InternalError(throwable); + } + } + + @Override + public void close() { + try { + impl.close(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new AssertionError(e); + } + } + + static CanCallJavaScope open() { + return CAN_CALL_JAVA_SCOPE != null ? new CanCallJavaScope() : null; + } + } + + @Override + public void notifyLowMemoryPoint(boolean suggestFullGC) { + LibGraalRuntime.notifyLowMemoryPoint(suggestFullGC); + } + + /** + * Since reference handling is synchronous in libgraal, explicitly perform it here and then run + * any code which is expecting to process a reference queue to let it clean up. + */ + public static void doReferenceHandling() { + LibGraalRuntime.processReferences(); + + /* + * Thanks to JDK-8346781, this can be replaced with jdk.vm.ci.hotspot.Cleaner.clean() once + * JDK 21 support is no longer necessary. + */ + LibGraalSubstitutions.Target_jdk_vm_ci_hotspot_Cleaner.clean(); + } + + @Override + public void fatalError(String crashMessage) { + LibGraalRuntime.fatalError(crashMessage); + } +} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/FromLibGraalCalls.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java similarity index 79% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/FromLibGraalCalls.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java index d774f3286525..9bc78ad4a1fb 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/FromLibGraalCalls.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot.libgraal; +package jdk.graal.compiler.libgraal.truffle; import com.oracle.truffle.compiler.hotspot.libgraal.FromLibGraalId; import org.graalvm.jniutils.JNI.JClass; @@ -31,6 +31,7 @@ import org.graalvm.jniutils.JNI.JObject; import org.graalvm.jniutils.JNI.JValue; import org.graalvm.jniutils.JNICalls; +import org.graalvm.jniutils.JNICalls.JNIMethod; import org.graalvm.jniutils.JNIExceptionWrapper; import org.graalvm.jniutils.JNIUtil; import org.graalvm.nativeimage.c.type.CTypeConversion; @@ -39,6 +40,10 @@ import java.util.EnumMap; import java.util.function.Function; +import static org.graalvm.jniutils.JNIUtil.ExceptionClear; +import static org.graalvm.jniutils.JNIUtil.GetStaticMethodID; +import static org.graalvm.nativeimage.c.type.CTypeConversion.toCString; + /** * Helpers for calling methods in HotSpot heap via JNI. */ @@ -54,47 +59,6 @@ protected FromLibGraalCalls(Class idType, JClass peer) { this.peer = peer; } - /** - * Describes a class and holds a reference to its {@linkplain #jclass JNI value}. - */ - static final class JNIClass { - final String className; - final JClass jclass; - - JNIClass(String className, JClass clazz) { - this.className = className; - this.jclass = clazz; - } - } - - /** - * Describes a method in HotSpot peer class}. - */ - static final class JNIMethodImpl & FromLibGraalId> implements JNICalls.JNIMethod { - final T hcId; - final JMethodID jniId; - - JNIMethodImpl(T hcId, JMethodID jniId) { - this.hcId = hcId; - this.jniId = jniId; - } - - @Override - public JMethodID getJMethodID() { - return jniId; - } - - @Override - public String getDisplayName() { - return hcId.getName(); - } - - @Override - public String toString() { - return hcId + "[0x" + Long.toHexString(jniId.rawValue()) + ']'; - } - } - JClass getPeer() { return peer; } @@ -103,6 +67,31 @@ JNICalls getJNICalls() { return hotSpotCalls; } + JNIMethod findJNIMethod(JNIEnv env, String methodName, Class returnType, Class... parameterTypes) { + try (CTypeConversion.CCharPointerHolder cname = toCString(methodName); + CTypeConversion.CCharPointerHolder csig = toCString(FromLibGraalId.encodeMethodSignature(returnType, parameterTypes))) { + JMethodID jniId = GetStaticMethodID(env, getPeer(), cname.get(), csig.get()); + if (jniId.isNull()) { + /* + * The `onFailure` method with 7 arguments is not available in Truffle runtime 24.0, + * clear pending NoSuchMethodError. + */ + ExceptionClear(env); + } + return new JNIMethod() { + @Override + public JMethodID getJMethodID() { + return jniId; + } + + @Override + public String getDisplayName() { + return methodName; + } + }; + } + } + public final void callVoid(JNIEnv env, T id, JValue args) { JNIMethodImpl method = getJNIMethod(env, id, void.class); hotSpotCalls.callStaticVoid(env, peer, method, args); @@ -152,4 +141,31 @@ public JNIMethodImpl apply(T id) { } } + /** + * Describes a method in HotSpot peer class}. + */ + private static final class JNIMethodImpl & FromLibGraalId> implements JNIMethod { + final T hcId; + final JMethodID jniId; + + JNIMethodImpl(T hcId, JMethodID jniId) { + this.hcId = hcId; + this.jniId = jniId; + } + + @Override + public JMethodID getJMethodID() { + return jniId; + } + + @Override + public String getDisplayName() { + return hcId.getName(); + } + + @Override + public String toString() { + return hcId + "[0x" + Long.toHexString(jniId.rawValue()) + ']'; + } + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSConsumer.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java similarity index 67% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSConsumer.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java index 29237f692c0d..9ae2c92528cc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSConsumer.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java @@ -22,34 +22,40 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal.truffle; +package jdk.graal.compiler.libgraal.truffle; import com.oracle.truffle.compiler.OptimizedAssumptionDependency; import com.oracle.truffle.compiler.TruffleCompilable; import com.oracle.truffle.compiler.TruffleCompilerAssumptionDependency; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.word.WordFactory; -import java.lang.invoke.MethodHandle; import java.util.function.Consumer; -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.ConsumeOptimizedAssumptionDependency; +import static org.graalvm.jniutils.JNIMethodScope.env; -final class HSConsumer extends HSIndirectHandle implements Consumer { +final class HSConsumer extends HSObject implements Consumer { - private static final Handles HANDLES = new Handles(); + private final TruffleFromLibGraalCalls calls; - HSConsumer(Object hsHandle) { - super(hsHandle); + HSConsumer(JNIMethodScope scope, JObject handle, TruffleFromLibGraalCalls calls) { + super(scope, handle); + this.calls = calls; } + @TruffleFromLibGraal(ConsumeOptimizedAssumptionDependency) @Override public void accept(OptimizedAssumptionDependency optimizedDependency) { TruffleCompilerAssumptionDependency dependency = (TruffleCompilerAssumptionDependency) optimizedDependency; - Object compilableHsHandle; + JObject compilable; long installedCode; if (dependency == null) { - compilableHsHandle = null; + compilable = WordFactory.nullPointer(); installedCode = 0; } else { TruffleCompilable ast = dependency.getCompilable(); @@ -58,20 +64,12 @@ public void accept(OptimizedAssumptionDependency optimizedDependency) { * Compilable may be null if the compilation was triggered by a libgraal host * compilation. */ - compilableHsHandle = null; + compilable = WordFactory.nullPointer(); } else { - compilableHsHandle = ((HSTruffleCompilable) dependency.getCompilable()).hsHandle; + compilable = ((HSTruffleCompilable) dependency.getCompilable()).getHandle(); } installedCode = HotSpotJVMCIRuntime.runtime().translate(dependency.getInstalledCode()); } - try { - HANDLES.consumeOptimizedAssumptionDependency.invoke(hsHandle, compilableHsHandle, installedCode); - } catch (Throwable t) { - throw handleException(t); - } - } - - private static final class Handles { - final MethodHandle consumeOptimizedAssumptionDependency = getHostMethodHandleOrFail(Id.ConsumeOptimizedAssumptionDependency); + HSConsumerGen.callConsumeOptimizedAssumptionDependency(calls, env(), getHandle(), compilable, installedCode); } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java new file mode 100644 index 000000000000..891e6a9d297c --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import com.oracle.truffle.compiler.TruffleCompilable; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.HotSpotGraalServices; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.SpeculationLog; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI; +import org.graalvm.jniutils.JNI.JByteArray; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNICalls; +import org.graalvm.jniutils.JNICalls.JNIMethod; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.nativebridge.BinaryInput; +import org.graalvm.nativeimage.StackValue; +import org.graalvm.word.WordFactory; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.AsJavaConstant; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.CancelCompilation; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.CompilableToString; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.CountDirectCallNodes; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.CreateStringSupplier; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.EngineId; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetCompilableCallCount; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetCompilableName; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetCompilerOptions; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetFailedSpeculationsAddress; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetKnownCallSiteCount; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetNonTrivialNodeCount; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsSameOrSplit; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsTrivial; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnCompilationFailed; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.PrepareForCompilation; +import static org.graalvm.jniutils.JNIMethodScope.env; +import static org.graalvm.jniutils.JNIUtil.createString; + +final class HSTruffleCompilable extends HSObject implements TruffleCompilable { + + private static volatile JNIMethod prepareForCompilationNewMethod; + private static volatile JNIMethod onCompilationSuccessMethod; + + private final TruffleFromLibGraalCalls calls; + /** + * Handle to {@code speculationLog} field of the {@code OptimizedCallTarget}. + */ + private Long cachedFailedSpeculationsAddress; + private volatile String cachedName; + private volatile String cachedString; + + HSTruffleCompilable(JNIMethodScope scope, JObject handle, HSTruffleCompilerRuntime runtime) { + super(scope, handle); + this.calls = runtime.calls; + } + + @TruffleFromLibGraal(GetFailedSpeculationsAddress) + @Override + public SpeculationLog getCompilationSpeculationLog() { + Long res = cachedFailedSpeculationsAddress; + if (res == null) { + res = HSTruffleCompilableGen.callGetFailedSpeculationsAddress(calls, env(), getHandle()); + cachedFailedSpeculationsAddress = res; + } + return HotSpotGraalServices.newHotSpotSpeculationLog(cachedFailedSpeculationsAddress); + } + + @TruffleFromLibGraal(GetCompilerOptions) + @Override + public Map getCompilerOptions() { + JNIEnv env = JNIMethodScope.env(); + JByteArray res = HSTruffleCompilableGen.callGetCompilerOptions(calls, env, getHandle()); + BinaryInput in = BinaryInput.create(JNIUtil.createArray(env, res)); + int size = in.readInt(); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < size; i++) { + String key = in.readUTF(); + map.put(key, in.readUTF()); + } + return map; + } + + @TruffleFromLibGraal(EngineId) + @Override + public long engineId() { + return HSTruffleCompilableGen.callEngineId(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(PrepareForCompilation) + @Override + public boolean prepareForCompilation(boolean rootCompilation, int compilationTier, boolean lastTier) { + JNIEnv env = JNIMethodScope.env(); + JNIMethod newMethod = findPrepareForCompilationNewMethod(env); + if (newMethod != null) { + return callPrepareForCompilationNew(newMethod, env, getHandle(), rootCompilation, compilationTier, lastTier); + } else { + HSTruffleCompilableGen.callPrepareForCompilation(calls, env(), getHandle()); + return true; + } + } + + private JNIMethod findPrepareForCompilationNewMethod(JNIEnv env) { + JNIMethod res = prepareForCompilationNewMethod; + if (res == null) { + res = calls.findJNIMethod(env, "prepareForCompilation", boolean.class, Object.class, boolean.class, int.class, boolean.class); + prepareForCompilationNewMethod = res; + } + return res.getJMethodID().isNonNull() ? res : null; + } + + private boolean callPrepareForCompilationNew(JNIMethod method, JNIEnv env, JObject p0, boolean p1, int p2, boolean p3) { + JNI.JValue args = StackValue.get(4, JNI.JValue.class); + args.addressOf(0).setJObject(p0); + args.addressOf(1).setBoolean(p1); + args.addressOf(2).setInt(p2); + args.addressOf(3).setBoolean(p3); + return calls.getJNICalls().callStaticBoolean(env, calls.getPeer(), method, args); + } + + @TruffleFromLibGraal(IsTrivial) + @Override + public boolean isTrivial() { + return HSTruffleCompilableGen.callIsTrivial(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(AsJavaConstant) + @Override + public JavaConstant asJavaConstant() { + long constantHandle = HSTruffleCompilableGen.callAsJavaConstant(calls, env(), getHandle()); + return HotSpotJVMCIRuntime.runtime().unhand(JavaConstant.class, constantHandle); + } + + @TruffleFromLibGraal(CreateStringSupplier) + @TruffleFromLibGraal(OnCompilationFailed) + @Override + public void onCompilationFailed(Supplier serializedException, boolean suppressed, boolean bailout, boolean permanentBailout, boolean graphTooBig) { + long serializedExceptionHandle = LibGraalObjectHandles.create(serializedException); + boolean success = false; + JNIEnv env = env(); + try { + JObject instance = HSTruffleCompilableGen.callCreateStringSupplier(calls, env, serializedExceptionHandle); + HSTruffleCompilableGen.callOnCompilationFailed(calls, env, getHandle(), instance, suppressed, bailout, permanentBailout, graphTooBig); + success = true; + } finally { + if (!success) { + LibGraalObjectHandles.remove(serializedExceptionHandle); + } + } + } + + @Override + public void onCompilationSuccess(int compilationTier, boolean lastTier) { + JNIEnv env = JNIMethodScope.env(); + JNICalls.JNIMethod methodOrNull = findOnCompilationSuccessMethod(env); + if (methodOrNull != null) { + JNI.JValue args = StackValue.get(3, JNI.JValue.class); + args.addressOf(0).setJObject(getHandle()); + args.addressOf(1).setInt(compilationTier); + args.addressOf(2).setBoolean(lastTier); + calls.getJNICalls().callStaticVoid(env, calls.getPeer(), methodOrNull, args); + } + } + + private JNIMethod findOnCompilationSuccessMethod(JNIEnv env) { + JNIMethod res = onCompilationSuccessMethod; + if (res == null) { + res = calls.findJNIMethod(env, "onCompilationSuccess", void.class, Object.class, int.class, boolean.class); + onCompilationSuccessMethod = res; + } + return res.getJMethodID().isNonNull() ? res : null; + } + + @Override + public boolean onInvalidate(Object source, CharSequence reason, boolean wasActive) { + throw GraalError.shouldNotReachHere("Should not be reachable."); // ExcludeFromJacocoGeneratedReport + } + + @TruffleFromLibGraal(GetCompilableName) + @Override + public String getName() { + String res = cachedName; + if (res == null) { + JNIEnv env = JNIMethodScope.env(); + res = JNIUtil.createString(env, HSTruffleCompilableGen.callGetCompilableName(calls, env, getHandle())); + cachedName = res; + } + return res; + } + + @TruffleFromLibGraal(CompilableToString) + @Override + public String toString() { + String res = cachedString; + if (res == null) { + JNIEnv env = JNIMethodScope.env(); + res = createString(env, HSTruffleCompilableGen.callCompilableToString(calls, env, getHandle())); + cachedString = res; + } + return res; + } + + @TruffleFromLibGraal(GetNonTrivialNodeCount) + @Override + public int getNonTrivialNodeCount() { + return HSTruffleCompilableGen.callGetNonTrivialNodeCount(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(CountDirectCallNodes) + @Override + public int countDirectCallNodes() { + return HSTruffleCompilableGen.callCountDirectCallNodes(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(GetCompilableCallCount) + @Override + public int getCallCount() { + return HSTruffleCompilableGen.callGetCompilableCallCount(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(CancelCompilation) + @Override + public boolean cancelCompilation(CharSequence reason) { + JNIEnv env = env(); + return HSTruffleCompilableGen.callCancelCompilation(calls, env, getHandle(), JNIUtil.createHSString(env, reason.toString())); + } + + @TruffleFromLibGraal(IsSameOrSplit) + @Override + public boolean isSameOrSplit(TruffleCompilable ast) { + JObject astHandle = ast == null ? WordFactory.nullPointer() : ((HSTruffleCompilable) ast).getHandle(); + return HSTruffleCompilableGen.callIsSameOrSplit(calls, env(), getHandle(), astHandle); + } + + @TruffleFromLibGraal(GetKnownCallSiteCount) + @Override + public int getKnownCallSiteCount() { + return HSTruffleCompilableGen.callGetKnownCallSiteCount(calls, env(), getHandle()); + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java new file mode 100644 index 000000000000..b9bc48926451 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import com.oracle.truffle.compiler.TruffleCompilable; +import com.oracle.truffle.compiler.TruffleCompilationTask; +import com.oracle.truffle.compiler.TruffleSourceLanguagePosition; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.JavaConstant; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI.JByteArray; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.nativebridge.BinaryInput; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.AddInlinedTarget; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.AddTargetToDequeue; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetDebugProperties; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetPosition; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.HasNextTier; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsCancelled; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsLastTier; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.SetCallCounts; +import static org.graalvm.jniutils.JNIMethodScope.env; + +final class HSTruffleCompilationTask extends HSObject implements TruffleCompilationTask { + + private final TruffleFromLibGraalCalls calls; + + HSTruffleCompilationTask(JNIMethodScope scope, JObject handle, HSTruffleCompilerRuntime runtime) { + super(scope, handle); + this.calls = runtime.calls; + } + + @TruffleFromLibGraal(IsCancelled) + @Override + public boolean isCancelled() { + return HSTruffleCompilationTaskGen.callIsCancelled(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(IsLastTier) + @Override + public boolean isLastTier() { + return HSTruffleCompilationTaskGen.callIsLastTier(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(HasNextTier) + @Override + public boolean hasNextTier() { + return HSTruffleCompilationTaskGen.callHasNextTier(calls, env(), getHandle()); + } + + @TruffleFromLibGraal(GetPosition) + @Override + public TruffleSourceLanguagePosition getPosition(JavaConstant node) { + long nodeHandle = HotSpotJVMCIRuntime.runtime().translate(node); + JObject res = HSTruffleCompilationTaskGen.callGetPosition(calls, env(), getHandle(), nodeHandle); + if (res.isNull()) { + return null; + } + return new HSTruffleSourceLanguagePosition(JNIMethodScope.scope(), res, calls); + } + + @TruffleFromLibGraal(AddTargetToDequeue) + @Override + public void addTargetToDequeue(TruffleCompilable target) { + JObject hsCompilable = ((HSTruffleCompilable) target).getHandle(); + HSTruffleCompilationTaskGen.callAddTargetToDequeue(calls, env(), getHandle(), hsCompilable); + } + + @TruffleFromLibGraal(SetCallCounts) + @Override + public void setCallCounts(int total, int inlined) { + HSTruffleCompilationTaskGen.callSetCallCounts(calls, env(), getHandle(), total, inlined); + } + + @TruffleFromLibGraal(AddInlinedTarget) + @Override + public void addInlinedTarget(TruffleCompilable target) { + JObject hsCompilable = ((HSTruffleCompilable) target).getHandle(); + HSTruffleCompilationTaskGen.callAddInlinedTarget(calls, env(), getHandle(), hsCompilable); + } + + @TruffleFromLibGraal(GetDebugProperties) + @Override + public Map getDebugProperties(JavaConstant node) { + long nodeHandle = HotSpotJVMCIRuntime.runtime().translate(node); + JNIEnv env = JNIMethodScope.env(); + byte[] bytes = JNIUtil.createArray(env, (JByteArray) HSTruffleCompilationTaskGen.callGetDebugProperties(calls, env, getHandle(), nodeHandle)); + BinaryInput in = BinaryInput.create(bytes); + Map result = new LinkedHashMap<>(); + int size = in.readInt(); + for (int i = 0; i < size; i++) { + String key = in.readUTF(); + Object value = in.readTypedValue(); + result.put(key, value); + } + return result; + } +} diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java new file mode 100644 index 000000000000..97d328f728a8 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import com.oracle.truffle.compiler.TruffleCompilable; +import com.oracle.truffle.compiler.TruffleCompilationTask; +import com.oracle.truffle.compiler.TruffleCompilerListener; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNI.JString; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; + +import java.util.function.Supplier; + +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnCompilationRetry; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnFailure; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnGraalTierFinished; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnSuccess; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnTruffleTierFinished; + +final class HSTruffleCompilerListener extends HSObject implements TruffleCompilerListener { + + private final TruffleFromLibGraalCalls calls; + + HSTruffleCompilerListener(JNIMethodScope scope, JObject handle, HSTruffleCompilerRuntime runtime) { + super(scope, handle); + this.calls = runtime.calls; + } + + @TruffleFromLibGraal(OnSuccess) + @Override + public void onSuccess(TruffleCompilable compilable, TruffleCompilationTask task, GraphInfo graphInfo, CompilationResultInfo compilationResultInfo, int tier) { + JObject hsCompilable = ((HSTruffleCompilable) compilable).getHandle(); + JObject hsTask = ((HSTruffleCompilationTask) task).getHandle(); + JNIEnv env = JNIMethodScope.env(); + try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graphInfo); + LibGraalObjectHandleScope compilationResultInfoScope = LibGraalObjectHandleScope.forObject(compilationResultInfo)) { + HSTruffleCompilerListenerGen.callOnSuccess(calls, env, getHandle(), hsCompilable, hsTask, graphInfoScope.getHandle(), compilationResultInfoScope.getHandle(), tier); + } + } + + @TruffleFromLibGraal(OnTruffleTierFinished) + @Override + public void onTruffleTierFinished(TruffleCompilable compilable, TruffleCompilationTask task, GraphInfo graph) { + JObject hsCompilable = ((HSTruffleCompilable) compilable).getHandle(); + JObject hsTask = ((HSTruffleCompilationTask) task).getHandle(); + JNIEnv env = JNIMethodScope.env(); + try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graph)) { + HSTruffleCompilerListenerGen.callOnTruffleTierFinished(calls, env, getHandle(), hsCompilable, hsTask, graphInfoScope.getHandle()); + } + } + + @TruffleFromLibGraal(OnGraalTierFinished) + @Override + public void onGraalTierFinished(TruffleCompilable compilable, GraphInfo graph) { + JObject hsCompilable = ((HSTruffleCompilable) compilable).getHandle(); + JNIEnv env = JNIMethodScope.env(); + try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graph)) { + HSTruffleCompilerListenerGen.callOnGraalTierFinished(calls, env, getHandle(), hsCompilable, graphInfoScope.getHandle()); + } + } + + @TruffleFromLibGraal(OnFailure) + @Override + public void onFailure(TruffleCompilable compilable, String reason, boolean bailout, boolean permanentBailout, int tier, Supplier lazyStackTrace) { + try (LibGraalObjectHandleScope lazyStackTraceScope = lazyStackTrace != null ? LibGraalObjectHandleScope.forObject(lazyStackTrace) : null) { + JObject hsCompilable = ((HSTruffleCompilable) compilable).getHandle(); + JNIEnv env = JNIMethodScope.env(); + JString hsReason = JNIUtil.createHSString(env, reason); + HSTruffleCompilerListenerGen.callOnFailure(calls, env, getHandle(), hsCompilable, hsReason, bailout, permanentBailout, tier, + lazyStackTraceScope != null ? lazyStackTraceScope.getHandle() : 0L); + } + } + + @TruffleFromLibGraal(OnCompilationRetry) + @Override + public void onCompilationRetry(TruffleCompilable compilable, TruffleCompilationTask task) { + JObject hsCompilable = ((HSTruffleCompilable) compilable).getHandle(); + JObject hsTask = ((HSTruffleCompilationTask) task).getHandle(); + JNIEnv env = JNIMethodScope.env(); + HSTruffleCompilerListenerGen.callOnCompilationRetry(calls, env, getHandle(), hsCompilable, hsTask); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerRuntime.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java similarity index 55% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerRuntime.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java index e645e0fb4cff..d2cf241da28f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerRuntime.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal.truffle; +package jdk.graal.compiler.libgraal.truffle; import com.oracle.truffle.compiler.ConstantFieldInfo; import com.oracle.truffle.compiler.HostMethodInfo; @@ -30,9 +30,10 @@ import com.oracle.truffle.compiler.PartialEvaluationMethodInfo; import com.oracle.truffle.compiler.TruffleCompilable; import com.oracle.truffle.compiler.TruffleCompilerRuntime; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; -import jdk.graal.compiler.debug.GraalError; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; +import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.serviceprovider.IsolateUtil; import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilationSupport; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -45,56 +46,67 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI.JByteArray; +import org.graalvm.jniutils.JNI.JClass; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNI.JString; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.nativebridge.BinaryInput; +import org.graalvm.nativeimage.StackValue; +import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.word.WordFactory; -import java.lang.invoke.MethodHandle; import java.util.Arrays; import java.util.function.Consumer; import java.util.function.Supplier; -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.CreateStringSupplier; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetConstantFieldInfo; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetPartialEvaluationMethodInfo; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsSuppressedFailure; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.IsValueType; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.Log; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnCodeInstallation; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnIsolateShutdown; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.RegisterOptimizedAssumptionDependency; +import static org.graalvm.jniutils.JNIMethodScope.env; +import static org.graalvm.jniutils.JNIMethodScope.scope; -final class HSTruffleCompilerRuntime extends HSIndirectHandle implements TruffleCompilerRuntime { - - private static final Handles HANDLES = new Handles(); +public final class HSTruffleCompilerRuntime extends HSObject implements TruffleCompilerRuntime { static final String COMPILER_VERSION = HotSpotTruffleCompilationSupport.readCompilerVersion(); - private static final Class TRANSLATED_EXCEPTION; - static { - Class clz; - try { - clz = Class.forName("jdk.internal.vm.TranslatedException"); - } catch (ClassNotFoundException cnf) { - clz = null; - } - TRANSLATED_EXCEPTION = clz; - } + // TranslatedException is package-private + private static final Class TRANSLATED_EXCEPTION = LibGraalFeature.lookupClass("jdk.internal.vm.TranslatedException"); private final ResolvedJavaType classLoaderDelegate; + final TruffleFromLibGraalCalls calls; - HSTruffleCompilerRuntime(Object hsHandle, long runtimeClass) { - super(hsHandle); - this.classLoaderDelegate = HotSpotJVMCIRuntime.runtime().asResolvedJavaType(runtimeClass); - if (this.classLoaderDelegate == null) { - throw GraalError.shouldNotReachHere("The object class needs to be available for a Truffle runtime object."); - } - NativeImageHostCalls.initializeHost(runtimeClass); + HSTruffleCompilerRuntime(JNIEnv env, JObject handle, ResolvedJavaType classLoaderDelegate, JClass peer) { + /* + * Note global duplicates may happen if the compiler is initialized by a host compilation. + */ + super(env, handle, true, false); + this.classLoaderDelegate = classLoaderDelegate; + this.calls = new TruffleFromLibGraalCalls(env, peer); } + @TruffleFromLibGraal(GetPartialEvaluationMethodInfo) @Override public PartialEvaluationMethodInfo getPartialEvaluationMethodInfo(ResolvedJavaMethod method) { long methodHandle = HotSpotJVMCIRuntime.runtime().translate(method); - byte[] array; - try { - array = (byte[]) HANDLES.getPartialEvaluationMethodInfo.invoke(hsHandle, methodHandle); - } catch (Throwable t) { - throw handleException(t); - } - LoopExplosionKind loopExplosionKind = LoopExplosionKind.values()[array[0]]; - InlineKind peInlineKind = InlineKind.values()[array[1]]; - InlineKind inlineKind = InlineKind.values()[array[2]]; - boolean inlineable = array[3] != 0; - boolean isSpecializationMethod = array[4] != 0; + JByteArray hsByteArray = HSTruffleCompilerRuntimeGen.callGetPartialEvaluationMethodInfo(calls, env(), getHandle(), methodHandle); + CCharPointer buffer = StackValue.get(5); + JNIUtil.GetByteArrayRegion(env(), hsByteArray, 0, 5, buffer); + BinaryInput in = BinaryInput.create(buffer, 5); + LoopExplosionKind loopExplosionKind = LoopExplosionKind.values()[in.readByte()]; + InlineKind peInlineKind = InlineKind.values()[in.readByte()]; + InlineKind inlineKind = InlineKind.values()[in.readByte()]; + boolean inlineable = in.readBoolean(); + boolean isSpecializationMethod = in.readBoolean(); return new PartialEvaluationMethodInfo(loopExplosionKind, peInlineKind, inlineKind, inlineable, isSpecializationMethod); } @@ -108,43 +120,39 @@ public TruffleCompilable asCompilableTruffleAST(JavaConstant constant) { if (constant.isNull()) { return null; } - long jniLocalRef = HotSpotJVMCIRuntime.runtime().getJObjectValue((HotSpotObjectConstant) constant); - Object compilableHsHandle = NativeImageHostCalls.createLocalHandleForLocalReference(jniLocalRef); - return compilableHsHandle == null ? null : new HSTruffleCompilable(compilableHsHandle); + JNIMethodScope scope = JNIMethodScope.scopeOrNull(); + if (scope == null) { + return null; + } + JObject hsCompilable = WordFactory.pointer(HotSpotJVMCIRuntime.runtime().getJObjectValue((HotSpotObjectConstant) constant)); + return new HSTruffleCompilable(scope, hsCompilable, this); } + @TruffleFromLibGraal(OnCodeInstallation) @Override public void onCodeInstallation(TruffleCompilable compilable, InstalledCode installedCode) { long installedCodeHandle = HotSpotJVMCIRuntime.runtime().translate(installedCode); - try { - HANDLES.onCodeInstallation.invoke(hsHandle, ((HSTruffleCompilable) compilable).hsHandle, installedCodeHandle); - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = env(); + HSTruffleCompilerRuntimeGen.callOnCodeInstallation(calls, env, getHandle(), ((HSTruffleCompilable) compilable).getHandle(), installedCodeHandle); } + @TruffleFromLibGraal(RegisterOptimizedAssumptionDependency) @Override public Consumer registerOptimizedAssumptionDependency(JavaConstant optimizedAssumption) { long optimizedAssumptionHandle = HotSpotJVMCIRuntime.runtime().translate(optimizedAssumption); - Object hsDependencyHandle; - try { - hsDependencyHandle = HANDLES.registerOptimizedAssumptionDependency.invoke(hsHandle, optimizedAssumptionHandle); - } catch (Throwable t) { - throw handleException(t); - } - return hsDependencyHandle == null ? null : new HSConsumer(hsDependencyHandle); + JNIEnv env = env(); + JObject assumptionConsumer = HSTruffleCompilerRuntimeGen.callRegisterOptimizedAssumptionDependency(calls, env, getHandle(), optimizedAssumptionHandle); + return assumptionConsumer.isNull() ? null : new HSConsumer(scope(), assumptionConsumer, calls); } + @TruffleFromLibGraal(IsValueType) @Override public boolean isValueType(ResolvedJavaType type) { long typeHandle = HotSpotJVMCIRuntime.runtime().translate(type); - try { - return (boolean) HANDLES.isValueType.invoke(hsHandle, typeHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilerRuntimeGen.callIsValueType(calls, env(), getHandle(), typeHandle); } + @TruffleFromLibGraal(GetConstantFieldInfo) @Override public ConstantFieldInfo getConstantFieldInfo(ResolvedJavaField field) { ResolvedJavaType enclosingType = field.getDeclaringClass(); @@ -166,12 +174,7 @@ public ConstantFieldInfo getConstantFieldInfo(ResolvedJavaField field) { Arrays.toString(declaredFields))); } long typeHandle = HotSpotJVMCIRuntime.runtime().translate(enclosingType); - int rawValue; - try { - rawValue = (int) HANDLES.getConstantFieldInfo.invoke(hsHandle, typeHandle, isStatic, fieldIndex); - } catch (Throwable t) { - throw handleException(t); - } + int rawValue = HSTruffleCompilerRuntimeGen.callGetConstantFieldInfo(calls, env(), getHandle(), typeHandle, isStatic, fieldIndex); return switch (rawValue) { case Integer.MIN_VALUE -> null; case -1 -> ConstantFieldInfo.CHILD; @@ -182,7 +185,7 @@ public ConstantFieldInfo getConstantFieldInfo(ResolvedJavaField field) { @Override public ResolvedJavaType resolveType(MetaAccessProvider metaAccess, String className, boolean required) { - String internalName = getInternalName(className); + String internalName = JNIUtil.getInternalName(className); JavaType jt; try { jt = HotSpotJVMCIRuntime.runtime().lookupType(internalName, (HotSpotResolvedObjectType) classLoaderDelegate, required); @@ -218,37 +221,36 @@ public ResolvedJavaType resolveType(MetaAccessProvider metaAccess, String classN return resolvedType; } - private static String getInternalName(String fqn) { - return "L" + fqn.replace('.', '/') + ";"; - } - + @TruffleFromLibGraal(Log) @Override public void log(String loggerId, TruffleCompilable compilable, String message) { - try { - HANDLES.log.invoke(hsHandle, loggerId, ((HSTruffleCompilable) compilable).hsHandle, message); - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = env(); + JString jniLoggerId = JNIUtil.createHSString(env, loggerId); + JString jniMessage = JNIUtil.createHSString(env, message); + HSTruffleCompilerRuntimeGen.callLog(calls, env, getHandle(), jniLoggerId, ((HSTruffleCompilable) compilable).getHandle(), jniMessage); } + @TruffleFromLibGraal(CreateStringSupplier) + @TruffleFromLibGraal(IsSuppressedFailure) @Override public boolean isSuppressedFailure(TruffleCompilable compilable, Supplier serializedException) { + long serializedExceptionHandle = LibGraalObjectHandles.create(serializedException); + boolean success = false; + JNIEnv env = env(); try { - Object supplierHsHandle = HANDLES.createStringSupplier.invoke(serializedException); - return (boolean) HANDLES.isSuppressedFailure.invoke(hsHandle, ((HSTruffleCompilable) compilable).hsHandle, supplierHsHandle); - } catch (Throwable t) { - throw handleException(t); + JObject instance = HSTruffleCompilerRuntimeGen.callCreateStringSupplier(calls, env, serializedExceptionHandle); + boolean res = HSTruffleCompilerRuntimeGen.callIsSuppressedFailure(calls, env, getHandle(), ((HSTruffleCompilable) compilable).getHandle(), instance); + success = true; + return res; + } finally { + if (!success) { + LibGraalObjectHandles.remove(serializedExceptionHandle); + } } } - private static final class Handles { - final MethodHandle getPartialEvaluationMethodInfo = getHostMethodHandleOrFail(Id.GetPartialEvaluationMethodInfo); - final MethodHandle onCodeInstallation = getHostMethodHandleOrFail(Id.OnCodeInstallation); - final MethodHandle registerOptimizedAssumptionDependency = getHostMethodHandleOrFail(Id.RegisterOptimizedAssumptionDependency); - final MethodHandle isValueType = getHostMethodHandleOrFail(Id.IsValueType); - final MethodHandle getConstantFieldInfo = getHostMethodHandleOrFail(Id.GetConstantFieldInfo); - final MethodHandle log = getHostMethodHandleOrFail(Id.Log); - final MethodHandle createStringSupplier = getHostMethodHandleOrFail(Id.CreateStringSupplier); - final MethodHandle isSuppressedFailure = getHostMethodHandleOrFail(Id.IsSuppressedFailure); + @TruffleFromLibGraal(OnIsolateShutdown) + public void notifyShutdown(JNIEnv env) { + HSTruffleCompilerRuntimeGen.callOnIsolateShutdown(calls, env, IsolateUtil.getIsolateID()); } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java new file mode 100644 index 000000000000..0b27e25e35e7 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import com.oracle.truffle.compiler.TruffleSourceLanguagePosition; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; +import org.graalvm.jniutils.HSObject; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; + +import java.net.URI; + +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetDescription; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetLanguage; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetLineNumber; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetNodeClassName; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetNodeId; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetOffsetEnd; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetOffsetStart; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.GetURI; + +final class HSTruffleSourceLanguagePosition extends HSObject implements TruffleSourceLanguagePosition { + + private final TruffleFromLibGraalCalls calls; + + HSTruffleSourceLanguagePosition(JNIMethodScope scope, JObject handle, TruffleFromLibGraalCalls calls) { + super(scope, handle); + this.calls = calls; + } + + @TruffleFromLibGraal(GetDescription) + @Override + public String getDescription() { + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetDescription(calls, env, getHandle())); + } + + @TruffleFromLibGraal(GetOffsetEnd) + @Override + public int getOffsetEnd() { + return HSTruffleSourceLanguagePositionGen.callGetOffsetEnd(calls, JNIMethodScope.env(), getHandle()); + } + + @TruffleFromLibGraal(GetOffsetStart) + @Override + public int getOffsetStart() { + return HSTruffleSourceLanguagePositionGen.callGetOffsetStart(calls, JNIMethodScope.env(), getHandle()); + } + + @TruffleFromLibGraal(GetLineNumber) + @Override + public int getLineNumber() { + return HSTruffleSourceLanguagePositionGen.callGetLineNumber(calls, JNIMethodScope.env(), getHandle()); + } + + @TruffleFromLibGraal(GetURI) + @Override + public URI getURI() { + JNIEnv env = JNIMethodScope.env(); + String stringifiedURI = JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetURI(calls, env, getHandle())); + return stringifiedURI == null ? null : URI.create(stringifiedURI); + } + + @TruffleFromLibGraal(GetLanguage) + @Override + public String getLanguage() { + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetLanguage(calls, env, getHandle())); + } + + @TruffleFromLibGraal(GetNodeId) + @Override + public int getNodeId() { + return HSTruffleSourceLanguagePositionGen.callGetNodeId(calls, JNIMethodScope.env(), getHandle()); + } + + @TruffleFromLibGraal(GetNodeClassName) + @Override + public String getNodeClassName() { + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetNodeClassName(calls, env, getHandle())); + } +} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandleScope.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java similarity index 93% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandleScope.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java index 3619c9c32819..4f0d03adee62 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandleScope.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot.libgraal; +package jdk.graal.compiler.libgraal.truffle; import java.io.Closeable; diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandles.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java similarity index 98% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandles.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java index 9e9819d0beb0..f3dcccabf4f1 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalObjectHandles.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot.libgraal; +package jdk.graal.compiler.libgraal.truffle; import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ObjectHandles; diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java new file mode 100644 index 000000000000..50612c3fd3c8 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import java.util.Objects; +import java.util.function.Supplier; + +import com.oracle.truffle.compiler.TruffleCompilationTask; +import jdk.graal.compiler.libgraal.LibGraalSupportImpl; +import jdk.graal.compiler.word.Word; +import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.jniutils.JNI.JByteArray; +import org.graalvm.jniutils.JNI.JClass; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNI.JObjectArray; +import org.graalvm.jniutils.JNI.JString; +import org.graalvm.jniutils.JNIExceptionWrapper; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.nativebridge.BinaryOutput; +import org.graalvm.nativeimage.ObjectHandles; +import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateThreadContext; +import org.graalvm.nativeimage.c.type.CLongPointer; +import org.graalvm.word.PointerBase; + +import com.oracle.truffle.compiler.TruffleCompilable; +import com.oracle.truffle.compiler.TruffleCompilerListener; +import com.oracle.truffle.compiler.TruffleCompilerListener.CompilationResultInfo; +import com.oracle.truffle.compiler.TruffleCompilerOptionDescriptor; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleToLibGraal; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleToLibGraal.Id; + +import jdk.graal.compiler.hotspot.CompilationContext; +import jdk.graal.compiler.hotspot.HotSpotGraalServices; +import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.libgraal.LibGraalJNIMethodScope; +import jdk.graal.compiler.truffle.TruffleCompilerOptions; +import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilationSupport; +import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; +import org.graalvm.nativeimage.libgraal.LibGraalRuntime; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Truffle specific {@link CEntryPoint} implementations. + */ +public class LibGraalTruffleEntryPoints { + + private static volatile int lastJavaPCOffset = -1; + + private static JNIMethodScope openScope(Enum id, JNIEnv env) { + Objects.requireNonNull(id, "Id must be non null."); + String scopeName = LibGraalTruffleEntryPoints.class.getSimpleName() + "::" + id; + int offset = lastJavaPCOffset; + if (offset == -1) { + HotSpotVMConfigAccess configAccess = new HotSpotVMConfigAccess(HotSpotJVMCIRuntime.runtime().getConfigStore()); + int anchor = configAccess.getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor"); + int lastJavaPc = configAccess.getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address"); + offset = anchor + lastJavaPc; + lastJavaPCOffset = offset; + } + + long currentJavaThread = HotSpotJVMCIRuntime.runtime().getCurrentJavaThread(); + CLongPointer currentThreadLastJavaPCOffset = (CLongPointer) Word.unsigned(currentJavaThread).add(offset); + PointerBase javaFrameAnchor = Word.pointer(currentThreadLastJavaPCOffset.read()); + return LibGraalJNIMethodScope.open(scopeName, env, javaFrameAnchor.isNonNull()); + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeIsolate", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.InitializeIsolate) + public static void initializeIsolate(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JClass runtimeClass) { + try (JNIMethodScope s = openScope(Id.InitializeIsolate, env)) { + // TruffleLibGraalShutdownHook.registerShutdownHook(env, runtimeClass); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_registerRuntime", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.RegisterRuntime) + public static boolean registerRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JObject truffleRuntime) { + try (JNIMethodScope s = openScope(Id.RegisterRuntime, env)) { + long truffleRuntimeWeakRef = JNIUtil.NewWeakGlobalRef(env, truffleRuntime, "TruffleCompilerRuntime").rawValue(); + return LibGraalTruffleHostEnvironmentLookup.registerRuntime(truffleRuntimeWeakRef); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return false; + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeRuntime", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.InitializeRuntime) + public static long initializeRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, + JObject truffleRuntime, JClass hsClassLoaderDelegate) { + try (JNIMethodScope s = openScope(Id.InitializeRuntime, env)) { + ResolvedJavaType classLoaderDelegate = HotSpotJVMCIRuntime.runtime().asResolvedJavaType(hsClassLoaderDelegate.rawValue()); + HSTruffleCompilerRuntime hsTruffleRuntime = new HSTruffleCompilerRuntime(env, truffleRuntime, classLoaderDelegate, hsClassLoaderDelegate); + LibGraalSupportImpl.registerTruffleCompilerRuntime(hsTruffleRuntime); + return LibGraalObjectHandles.create(hsTruffleRuntime); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0L; + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_newCompiler", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.NewCompiler) + public static long newCompiler(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long truffleRuntimeHandle) { + try (JNIMethodScope s = openScope(Id.NewCompiler, env)) { + Object truffleRuntime = LibGraalObjectHandles.resolve(truffleRuntimeHandle, Object.class); + /* + * Unlike `LibGraalTruffleHostEnvironment`, Truffle libgraal entry points use the global + * compilation context by default, so we don't need to call + * `HotSpotGraalServices.enterGlobalCompilationContext()` before creating + * `TruffleCompilerImpl`. The `doCompile` method enters a local compilation context + * through its own call to `HotSpotGraalServices.openLocalCompilationContext`. + */ + HotSpotTruffleCompilerImpl compiler = HotSpotTruffleCompilerImpl.create((HSTruffleCompilerRuntime) truffleRuntime, null); + return LibGraalObjectHandles.create(compiler); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @SuppressWarnings("unused") + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeCompiler", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.InitializeRuntime) + public static void initializeCompiler(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long compilerHandle, JObject hsCompilable, + boolean firstInitialization) { + try (JNIMethodScope scope = openScope(Id.InitializeCompiler, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(compilerHandle, HotSpotTruffleCompilerImpl.class); + HSTruffleCompilerRuntime runtime = (HSTruffleCompilerRuntime) compiler.getConfig().runtime(); + TruffleCompilable compilable = new HSTruffleCompilable(scope, hsCompilable, runtime); + compiler.initialize(compilable, firstInitialization); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getCompilerConfigurationFactoryName", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.GetCompilerConfigurationFactoryName) + public static JString getCompilerConfigurationFactoryName(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long truffleRuntimeHandle) { + try { + JNIMethodScope scope = openScope(Id.GetCompilerConfigurationFactoryName, env); + try (JNIMethodScope s = scope) { + String name = HotSpotTruffleCompilationSupport.getLazyCompilerConfigurationName(); + scope.setObjectResult(JNIUtil.createHSString(env, name)); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_doCompile", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.DoCompile) + public static void doCompile(JNIEnv env, + JClass hsClazz, + @IsolateThreadContext long isolateThreadAddress, + long compilerHandle, + JObject hsTask, + JObject hsCompilable, + JObject hsListener) { + try (JNIMethodScope scope = openScope(Id.DoCompile, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(compilerHandle, HotSpotTruffleCompilerImpl.class); + HSTruffleCompilerRuntime runtime = (HSTruffleCompilerRuntime) compiler.getConfig().runtime(); + TruffleCompilationTask task = hsTask.isNull() ? null : new HSTruffleCompilationTask(scope, hsTask, runtime); + HSTruffleCompilable compilable = new HSTruffleCompilable(scope, hsCompilable, runtime); + TruffleCompilerListener listener = hsListener.isNull() ? null : new HSTruffleCompilerListener(scope, hsListener, runtime); + try (CompilationContext hotSpotObjectConstantScope = HotSpotGraalServices.openLocalCompilationContext(compilable)) { + compiler.doCompile(task, compilable, listener); + } finally { + LibGraalRuntime.processReferences(); + LibGraalRuntime.notifyLowMemoryPoint(true); + } + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_shutdown", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.Shutdown) + public static void shutdown(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.Shutdown, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(handle, HotSpotTruffleCompilerImpl.class); + compiler.shutdown(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_installTruffleCallBoundaryMethod", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.InstallTruffleCallBoundaryMethod) + public static void installTruffleCallBoundaryMethod(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, long methodHandle) { + try (JNIMethodScope s = openScope(Id.InstallTruffleCallBoundaryMethod, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(handle, HotSpotTruffleCompilerImpl.class); + compiler.installTruffleCallBoundaryMethod(HotSpotJVMCIRuntime.runtime().unhand(ResolvedJavaMethod.class, methodHandle), null); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_installTruffleReservedOopMethod", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.InstallTruffleReservedOopMethod) + public static void installTruffleReservedOopMethod(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, long methodHandle) { + try (JNIMethodScope s = openScope(Id.InstallTruffleReservedOopMethod, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(handle, HotSpotTruffleCompilerImpl.class); + compiler.installTruffleReservedOopMethod(HotSpotJVMCIRuntime.runtime().unhand(ResolvedJavaMethod.class, methodHandle), null); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @SuppressWarnings("unused") + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_pendingTransferToInterpreterOffset", include = LibGraalFeature.IsEnabled.class) + @TruffleToLibGraal(Id.PendingTransferToInterpreterOffset) + public static int pendingTransferToInterpreterOffset(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, JObject hsCompilable) { + try (JNIMethodScope scope = openScope(Id.PendingTransferToInterpreterOffset, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(handle, HotSpotTruffleCompilerImpl.class); + HSTruffleCompilerRuntime runtime = (HSTruffleCompilerRuntime) compiler.getConfig().runtime(); + TruffleCompilable compilable = new HSTruffleCompilable(scope, hsCompilable, runtime); + return compiler.pendingTransferToInterpreterOffset(compilable); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getSuppliedString", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try", "unchecked"}) + @TruffleToLibGraal(Id.GetSuppliedString) + public static JString getSuppliedString(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try { + JNIMethodScope scope = openScope(Id.GetSuppliedString, env); + try (JNIMethodScope s = scope) { + Supplier stringSupplier = LibGraalObjectHandles.resolve(handle, Supplier.class); + if (stringSupplier != null) { + String stackTrace = stringSupplier.get(); + scope.setObjectResult(JNIUtil.createHSString(env, stackTrace)); + } else { + scope.setObjectResult(Word.nullPointer()); + } + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getNodeCount", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetNodeCount) + public static int getNodeCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetNodeCount, env)) { + Object graphInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.GraphInfo) graphInfo).getNodeCount(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getNodeTypes", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetNodeTypes) + public static JObjectArray getNodeTypes(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, boolean simpleNames) { + try { + JNIMethodScope scope = openScope(Id.GetNodeTypes, env); + try (JNIMethodScope s = scope) { + Object graphInfo = LibGraalObjectHandles.resolve(handle, Object.class); + String[] nodeTypes = ((TruffleCompilerListener.GraphInfo) graphInfo).getNodeTypes(simpleNames); + JClass componentType = getStringClass(env); + JObjectArray res = JNIUtil.NewObjectArray(env, nodeTypes.length, componentType, Word.nullPointer()); + for (int i = 0; i < nodeTypes.length; i++) { + JNIUtil.SetObjectArrayElement(env, res, i, JNIUtil.createHSString(env, nodeTypes[i])); + } + scope.setObjectResult(res); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + private static JClass getStringClass(JNIEnv env) { + return JNIUtil.NewGlobalRef(env, JNIUtil.findClass(env, "java/lang/String"), "Class"); + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls2_getCompilationId", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetCompilationId) + public static long getCompilationId(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetCompilationId, env)) { + CompilationResultInfo compilationResultInfo = LibGraalObjectHandles.resolve(handle, CompilationResultInfo.class); + return compilationResultInfo.getCompilationId(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getTargetCodeSize", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetTargetCodeSize) + public static int getTargetCodeSize(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetTargetCodeSize, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getTargetCodeSize(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getTotalFrameSize", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetTotalFrameSize) + public static int getTotalFrameSize(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetTotalFrameSize, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getTotalFrameSize(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getExceptionHandlersCount", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetExceptionHandlersCount) + public static int getExceptionHandlersCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetExceptionHandlersCount, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getExceptionHandlersCount(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getInfopointsCount", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetInfopointsCount) + public static int getInfopointsCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetInfopointsCount, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getInfopointsCount(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getInfopoints", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetInfopoints) + public static JObjectArray getInfopoints(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try { + JNIMethodScope scope = openScope(Id.GetInfopoints, env); + try (JNIMethodScope s = scope) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + String[] infoPoints = ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getInfopoints(); + JClass componentType = getStringClass(env); + JObjectArray res = JNIUtil.NewObjectArray(env, infoPoints.length, componentType, Word.nullPointer()); + for (int i = 0; i < infoPoints.length; i++) { + JNIUtil.SetObjectArrayElement(env, res, i, JNIUtil.createHSString(env, infoPoints[i])); + } + scope.setObjectResult(res); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getMarksCount", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetMarksCount) + public static int getMarksCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetMarksCount, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getMarksCount(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getDataPatchesCount", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetDataPatchesCount) + public static int getDataPatchesCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { + try (JNIMethodScope s = openScope(Id.GetDataPatchesCount, env)) { + Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); + return ((TruffleCompilerListener.CompilationResultInfo) compilationResultInfo).getDataPatchesCount(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return 0; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_listCompilerOptions", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.ListCompilerOptions) + public static JByteArray listCompilerOptions(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress) { + try { + JNIMethodScope scope = openScope(Id.ListCompilerOptions, env); + try (JNIMethodScope s = scope) { + TruffleCompilerOptionDescriptor[] options = TruffleCompilerOptions.listOptions(); + BinaryOutput.ByteArrayBinaryOutput out = BinaryOutput.create(); + out.writeInt(options.length); + for (TruffleCompilerOptionDescriptor option : options) { + out.writeUTF(option.name()); + out.writeInt(option.type().ordinal()); + out.writeBoolean(option.deprecated()); + out.writeUTF(option.help()); + out.writeUTF(option.deprecationMessage()); + } + JByteArray res = JNIUtil.createHSArray(env, out.getArray()); + scope.setObjectResult(res); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_compilerOptionExists", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.CompilerOptionExists) + public static boolean compilerOptionExists(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JString optionName) { + try (JNIMethodScope scope = openScope(Id.CompilerOptionExists, env)) { + String optionName1 = JNIUtil.createString(env, optionName); + return TruffleCompilerOptions.optionExists(optionName1); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return false; + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_validateCompilerOption", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.ValidateCompilerOption) + public static JString validateCompilerOption(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JString optionName, JString optionValue) { + try { + JNIMethodScope scope = openScope(Id.ValidateCompilerOption, env); + try (JNIMethodScope s = scope) { + String optionName1 = JNIUtil.createString(env, optionName); + String result = TruffleCompilerOptions.validateOption(optionName1, JNIUtil.createString(env, optionValue)); + scope.setObjectResult(JNIUtil.createHSString(env, result)); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_purgePartialEvaluationCaches", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.PurgePartialEvaluationCaches) + public static void purgePartialEvaluationCaches(JNIEnv env, JClass hsClass, @IsolateThreadContext long isolateThreadAddress, long compilerHandle) { + try (JNIMethodScope s = openScope(Id.PurgePartialEvaluationCaches, env)) { + HotSpotTruffleCompilerImpl compiler = LibGraalObjectHandles.resolve(compilerHandle, HotSpotTruffleCompilerImpl.class); + if (compiler != null) { + compiler.purgePartialEvaluationCaches(); + } + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getCompilerVersion", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings({"unused", "try"}) + @TruffleToLibGraal(Id.GetCompilerVersion) + public static JString getCompilerVersion(JNIEnv env, JClass hsClass, @IsolateThreadContext long isolateThreadAddress) { + try { + JNIMethodScope scope = openScope(Id.GetCompilerVersion, env); + try (JNIMethodScope s = scope) { + String version = HSTruffleCompilerRuntime.COMPILER_VERSION; + scope.setObjectResult(JNIUtil.createHSString(env, version)); + } + return scope.getObjectResult(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return Word.nullPointer(); + } + } + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalObject_releaseHandle", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings("unused") + public static boolean releaseHandle(JNIEnv jniEnv, JClass jclass, @IsolateThreadContext long isolateThreadAddress, long handle) { + try { + ObjectHandles.getGlobal().destroy(Word.pointer(handle)); + return true; + } catch (Throwable t) { + return false; + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java similarity index 96% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironment.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java index 3ac8c3faa522..1adaebafda5a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironment.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal.truffle; +package jdk.graal.compiler.libgraal.truffle; import com.oracle.truffle.compiler.HostMethodInfo; import com.oracle.truffle.compiler.TruffleCompilable; @@ -30,6 +30,7 @@ import jdk.graal.compiler.core.common.util.MethodKey; import jdk.graal.compiler.hotspot.CompilationContext; import jdk.graal.compiler.hotspot.HotSpotGraalServices; +import jdk.graal.compiler.serviceprovider.JavaVersionUtil; import jdk.graal.compiler.truffle.TruffleCompilerImpl; import jdk.graal.compiler.truffle.TruffleElementCache; import jdk.graal.compiler.truffle.host.TruffleHostEnvironment; @@ -131,10 +132,9 @@ private static MethodHandle findCompilerThreadCanCallJavaScopeConstructor() { try { return MethodHandles.lookup().findConstructor(Class.forName("jdk.vm.ci.hotspot.CompilerThreadCanCallJavaScope"), MethodType.methodType(void.class, boolean.class)); } catch (ReflectiveOperationException e) { -// GR-58987: Uncomment when OpenJDK pull request is merged -// if (Runtime.version().feature() >= 24) { -// throw new InternalError(e); -// } + if (JavaVersionUtil.JAVA_SPEC != 21) { + throw new InternalError(e); + } } return null; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java similarity index 73% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java index be7781e34e08..b062f69c706f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java @@ -22,14 +22,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal.truffle; +package jdk.graal.compiler.libgraal.truffle; +import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; import jdk.graal.compiler.truffle.host.TruffleHostEnvironment; import jdk.graal.compiler.truffle.host.TruffleHostEnvironment.TruffleRuntimeScope; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.jniutils.JNI.JClass; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JObject; +import org.graalvm.jniutils.JNIMethodScope; +import org.graalvm.jniutils.JNIUtil; +import org.graalvm.word.WordFactory; /** * This handles the Truffle host environment lookup on HotSpot with Libgraal. @@ -47,9 +53,9 @@ public final class LibGraalTruffleHostEnvironmentLookup implements TruffleHostEnvironment.Lookup { private static final int NO_TRUFFLE_REGISTERED = 0; - private static final GlobalAtomicLong WEAK_TRUFFLE_RUNTIME_INSTANCE = new GlobalAtomicLong(NO_TRUFFLE_REGISTERED); + private static final GlobalAtomicLong WEAK_TRUFFLE_RUNTIME_INSTANCE = new GlobalAtomicLong("WEAK_TRUFFLE_RUNTIME_INSTANCE", NO_TRUFFLE_REGISTERED); - @NativeImageReinitialize private TruffleHostEnvironment previousRuntime; + private TruffleHostEnvironment previousRuntime; @Override @SuppressWarnings("try") @@ -59,26 +65,33 @@ public TruffleHostEnvironment lookup(ResolvedJavaType forType) { // fast path if Truffle was not initialized return null; } - Object runtimeLocalHandle = NativeImageHostCalls.createLocalHandleForWeakGlobalReference(globalReference); - if (runtimeLocalHandle == null) { + JNIEnv env = JNIMethodScope.env(); + JObject runtimeLocalRef = JNIUtil.NewLocalRef(env, WordFactory.pointer(globalReference)); + if (runtimeLocalRef.isNull()) { // The Truffle runtime was collected by the GC return null; } TruffleHostEnvironment environment = this.previousRuntime; if (environment != null) { - Object cached = hsRuntime(environment).hsHandle; - if (NativeImageHostCalls.isSameObject(cached, runtimeLocalHandle)) { + JObject cached = hsRuntime(environment).getHandle(); + if (JNIUtil.IsSameObject(env, cached, runtimeLocalRef)) { // fast path for registered and cached Truffle runtime handle return environment; } } + JClass runtimeClass = JNIUtil.GetObjectClass(env, runtimeLocalRef); + ResolvedJavaType runtimeType = HotSpotJVMCIRuntime.runtime().asResolvedJavaType(runtimeClass.rawValue()); + if (runtimeType == null) { + throw GraalError.shouldNotReachHere("The object class needs to be available for a Truffle runtime object."); + } /* * We do not currently validate the forType. But in the future we want to lookup the runtime * per type. So in theory multiple truffle runtimes can be loaded. */ - try (TruffleRuntimeScope scope = LibGraalTruffleHostEnvironment.openTruffleRuntimeScopeImpl()) { - HSTruffleCompilerRuntime runtime = new HSTruffleCompilerRuntime(NativeImageHostCalls.createGlobalHandle(runtimeLocalHandle, true), NativeImageHostCalls.getObjectClass(runtimeLocalHandle)); + try (TruffleRuntimeScope truffleRuntimeScope = LibGraalTruffleHostEnvironment.openTruffleRuntimeScopeImpl()) { + HSTruffleCompilerRuntime runtime = new HSTruffleCompilerRuntime(env, runtimeLocalRef, runtimeType, runtimeClass); this.previousRuntime = environment = new LibGraalTruffleHostEnvironment(runtime, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getMetaAccess()); + assert JNIUtil.IsSameObject(env, hsRuntime(environment).getHandle(), runtimeLocalRef); return environment; } } @@ -87,7 +100,7 @@ private static HSTruffleCompilerRuntime hsRuntime(TruffleHostEnvironment environ return (HSTruffleCompilerRuntime) environment.runtime(); } - static boolean registerRuntime(long truffleRuntimeWeakRef) { + public static boolean registerRuntime(long truffleRuntimeWeakRef) { // TODO GR-44222 support multiple runtimes. return WEAK_TRUFFLE_RUNTIME_INSTANCE.compareAndSet(0, truffleRuntimeWeakRef); } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java new file mode 100644 index 000000000000..85612be8a82d --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.libgraal.truffle; + +import org.graalvm.nativeimage.Isolate; +import org.graalvm.nativeimage.IsolateThread; +import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.word.PointerBase; + +import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.serviceprovider.IsolateUtil; + +/** + * Truffle specific {@link CEntryPoint} implementations. + */ +final class LibGraalTruffleScopeEntryPoints { + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_getIsolateThreadIn", builtin = CEntryPoint.Builtin.GET_CURRENT_THREAD, include = LibGraalFeature.IsEnabled.class) + private static native IsolateThread getIsolateThreadIn(PointerBase env, PointerBase hsClazz, @CEntryPoint.IsolateContext Isolate isolate); + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_attachThreadTo", builtin = CEntryPoint.Builtin.ATTACH_THREAD, include = LibGraalFeature.IsEnabled.class) + static native long attachThreadTo(PointerBase env, PointerBase hsClazz, @CEntryPoint.IsolateContext long isolate); + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_detachThreadFrom", builtin = CEntryPoint.Builtin.DETACH_THREAD, include = LibGraalFeature.IsEnabled.class) + static native void detachThreadFrom(PointerBase env, PointerBase hsClazz, @CEntryPoint.IsolateThreadContext long isolateThreadAddress); + + @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_getIsolateId", include = LibGraalFeature.IsEnabled.class) + @SuppressWarnings("unused") + public static long getIsolateId(PointerBase env, PointerBase jclass, @CEntryPoint.IsolateThreadContext long isolateThreadAddress) { + return IsolateUtil.getIsolateID(); + } +} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalCalls.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java similarity index 94% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalCalls.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java index 644cee8f9809..f32440524246 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalCalls.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.graal.hotspot.libgraal; +package jdk.graal.compiler.libgraal.truffle; import static org.graalvm.jniutils.JNIUtil.NewGlobalRef; diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CompilationWatchDogTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CompilationWatchDogTest.java index 2d03881a91ca..0b71b4fd77f2 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CompilationWatchDogTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CompilationWatchDogTest.java @@ -137,7 +137,7 @@ public void onStuckCompilation(CompilationWatchDog watchDog, Thread watched, Com }; - CompilationWatchDog watch = CompilationWatchDog.watch(compilation, options, false, longCompilationHandler); + CompilationWatchDog watch = CompilationWatchDog.watch(compilation, options, false, longCompilationHandler, null); try (CompilationWatchDog watchScope = watch) { event("start compiling"); try (TTY.Filter f = new TTY.Filter()) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyAssertionUsage.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyAssertionUsage.java index c2fa9631600a..c7e857b6a09f 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyAssertionUsage.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyAssertionUsage.java @@ -122,7 +122,7 @@ public class VerifyAssertionUsage extends VerifyStringFormatterUsage { private final boolean log; /* - * GR-49601: only check non boolean assertion calls for now. + * GR-49601: only check non-boolean assertion calls for now. */ private final boolean verifyBooleanAssertionConditions; @@ -471,19 +471,19 @@ private void reportSuperfluousAssertions(StringBuilder allErrorMessages) { } private void reportMissingAssertions(StringBuilder allErrorMessages) { - StringBuilder sbMissingAssertionMessages = new StringBuilder(); + List missingAssertionMessages = new ArrayList<>(); for (AssertionCall ac : assertionCallsWithoutMessage) { ResolvedJavaMethod callee = ac.callee; if (callee == null || !getMethodInfo(callee).canBeCalledWithoutErrorMessage()) { - sbMissingAssertionMessages.append(formatNSP(ac.nsp)).append(System.lineSeparator()); + missingAssertionMessages.add(formatNSP(ac.nsp)); } } - if (!sbMissingAssertionMessages.isEmpty()) { - allErrorMessages.append(String.format("Found the following assertions that need error messages %n%s%n " + - "This is because you added a new assertion without an error message. " + - "Please fix all assertions in the report above such that they have error messages." + - "Consider using API from " + Assertions.class.getName() + " to format assertion error messages with more context.", - sbMissingAssertionMessages)); + if (!missingAssertionMessages.isEmpty()) { + String sep = String.format("%n "); + allErrorMessages.append(String.format("Found the assertions that need error messages at:%s%s%n" + + "Please fix all above assertions such that they have error messages. " + + "Consider using API from %s to format assertion error messages with more context.", + sep, String.join(sep, missingAssertionMessages), Assertions.class)); allErrorMessages.append(System.lineSeparator()); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java index 10a48b8aa4da..5c67cf2d7f15 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java @@ -40,12 +40,10 @@ /** * Ensures that the only code directly accessing - * {@link jdk.vm.ci.services.Services#IS_IN_NATIVE_IMAGE} and - * {@link jdk.vm.ci.services.Services#IS_BUILDING_NATIVE_IMAGE} is in + * {@link jdk.vm.ci.services.Services#IS_IN_NATIVE_IMAGE} is in * {@link jdk.graal.compiler.serviceprovider.GraalServices}. All other code must use one of the * following methods: *
    - *
  • {@link GraalServices#isBuildingLibgraal()}
  • *
  • {@link GraalServices#isInLibgraal()}
  • *
  • {@link ImageInfo#inImageCode()}
  • *
  • {@link ImageInfo#inImageBuildtimeCode()}
  • @@ -79,14 +77,12 @@ protected void verify(StructuredGraph graph, CoreProviders context) { for (LoadFieldNode load : loads) { ResolvedJavaField field = load.field(); if (field.getDeclaringClass().toJavaName().equals(Services.class.getName())) { - if (field.getName().equals("IS_BUILDING_NATIVE_IMAGE") || field.getName().equals("IS_IN_NATIVE_IMAGE")) { + if (field.getName().equals("IS_IN_NATIVE_IMAGE")) { if (!isAllowedToAccess(graph.method())) { - String recommendation = field.getName().equals("IS_BUILDING_NATIVE_IMAGE") ? "isBuildingLibgraal" : "isInLibgraal"; - throw new VerificationError("reading %s in %s is prohibited - use %s.%s() instead", + throw new VerificationError("reading %s in %s is prohibited - use %s.isInLibgraal() instead", field.format("%H.%n"), graph.method().format("%H.%n(%p)"), - GraalServices.class.getName(), - recommendation); + GraalServices.class.getName()); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalOptionValuesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalOptionValuesTest.java index 4cea3c49826d..3d848fb32a69 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalOptionValuesTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalOptionValuesTest.java @@ -97,26 +97,4 @@ public void testDeprecation() throws IOException, InterruptedException { expect, matches, proc.preserveArgfile())); } } - - @Test - public void testRemoved() throws IOException, InterruptedException { - List vmArgs = withoutDebuggerArguments(getVMCommandLine()); - vmArgs.removeIf(a -> a.startsWith("-Djdk.graal.")); - vmArgs.add("-XX:+UseJVMCICompiler"); - vmArgs.add("-Djdk.libgraal.PrintGC=true"); - vmArgs.add("-XX:+EagerJVMCI"); - vmArgs.add("--version"); - SubprocessUtil.Subprocess proc = SubprocessUtil.java(vmArgs); - - if (proc.exitCode == 0) { - Assert.fail(String.format("Expected non-0 exit code%n%s", proc.preserveArgfile())); - } - - String expect = "Error parsing Graal options: The 'jdk.libgraal.' property prefix is no longer supported. Use jdk.graal.internal."; - long matches = proc.output.stream().filter(line -> line.contains(expect)).count(); - if (matches != 1) { - Assert.fail(String.format("Did not find exactly 1 match for '%s' in output of command [matches: %d]:%n%s", - expect, matches, proc.preserveArgfile())); - } - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java index ddf4d39ffcc6..1dc4e9a2e218 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java @@ -42,7 +42,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.serviceprovider.IsolateUtil; -import jdk.vm.ci.common.NativeImageReinitialize; /** * A watch dog for {@linkplain #watch watching} and reporting on long running compilations. @@ -182,19 +181,21 @@ public static class Options { private final ScheduledExecutorService singleShotExecutor; - CompilationWatchDog(CompilationIdentifier compilation, Thread watchedThread, int delay, int vmExitDelay, - boolean singleShotExecutor, EventHandler eventHandler) { + CompilationWatchDog(CompilationIdentifier compilation, + Thread watchedThread, int delay, int vmExitDelay, + boolean singleShotExecutor, EventHandler eventHandler, + ThreadFactory factory) { this.compilation = compilation; this.watchedThread = watchedThread; this.vmExitDelayNS = TimeUnit.SECONDS.toNanos(vmExitDelay); this.eventHandler = eventHandler == null ? EventHandler.DEFAULT : eventHandler; trace("started compiling %s", compilation); if (singleShotExecutor) { - this.singleShotExecutor = createExecutor(); + this.singleShotExecutor = createExecutor(factory); this.task = this.singleShotExecutor.schedule(this, delay, TimeUnit.SECONDS); } else { this.singleShotExecutor = null; - this.task = schedule(this, delay); + this.task = schedule(this, delay, factory); } } @@ -292,29 +293,26 @@ public void run() { } } - @NativeImageReinitialize private static ScheduledExecutorService watchDogService; + private static ScheduledExecutorService watchDogService; - private static synchronized ScheduledFuture schedule(CompilationWatchDog watchdog, int delay) { + private static synchronized ScheduledFuture schedule(CompilationWatchDog watchdog, int delay, ThreadFactory factory) { if (watchDogService == null) { - watchDogService = createExecutor(); + watchDogService = createExecutor(factory); } return watchDogService.schedule(watchdog, delay, TimeUnit.SECONDS); } - private static ScheduledExecutorService createExecutor() { - ThreadFactory threadFactory = new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread thread = new GraalServiceThread(CompilationWatchDog.class.getSimpleName(), r); - thread.setName("WatchDog-" + GraalServices.getThreadId(thread)); - thread.setPriority(Thread.MAX_PRIORITY); - thread.setDaemon(true); - return thread; - } + private static ScheduledExecutorService createExecutor(ThreadFactory factory) { + ThreadFactory watchDogThreadFactory = r -> { + Thread thread = factory == null ? new Thread(r) : factory.newThread(r); + thread.setName("WatchDog-" + GraalServices.getThreadId(thread)); + thread.setPriority(Thread.MAX_PRIORITY); + thread.setDaemon(true); + return thread; }; int poolSize = 1; - ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(poolSize, threadFactory); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(poolSize, watchDogThreadFactory); executor.setRemoveOnCancelPolicy(true); executor.allowCoreThreadTimeOut(true); return executor; @@ -324,16 +322,19 @@ public Thread newThread(Runnable r) { * Opens a scope for watching a compilation. * * @param compilation identifies the compilation being watched - * @param singleShotExecutor if true, then a dedicated executor is created for this task and it + * @param singleShotExecutor if true, then a dedicated executor is created for this task, and it * is shutdown once the compilation ends - * @param eventHandler notified of events like a compilation running long running or getting - * stuck. If {@code null}, {@link EventHandler#DEFAULT} is used. + * @param eventHandler notified of events like a compilation running long or getting stuck. If + * {@code null}, {@link EventHandler#DEFAULT} is used. + * @param factory factory to use for creating the watcher thread. If null, a default Thread + * object is used. * @return {@code null} if the compilation watch dog is disabled otherwise a new * {@link CompilationWatchDog} object. The returned value should be used in a * {@code try}-with-resources statement whose scope is the whole compilation so that * leaving the scope will cause {@link #close()} to be called. */ - public static CompilationWatchDog watch(CompilationIdentifier compilation, OptionValues options, boolean singleShotExecutor, EventHandler eventHandler) { + public static CompilationWatchDog watch(CompilationIdentifier compilation, OptionValues options, + boolean singleShotExecutor, EventHandler eventHandler, ThreadFactory factory) { int delay = Options.CompilationWatchDogStartDelay.getValue(options); if (ImageInfo.inImageBuildtimeCode() && !Options.CompilationWatchDogStartDelay.hasBeenSet(options)) { // Disable watch dog by default when building a native image @@ -342,9 +343,8 @@ public static CompilationWatchDog watch(CompilationIdentifier compilation, Optio if (delay > 0) { Thread watchedThread = Thread.currentThread(); int vmExitDelay = Options.CompilationWatchDogVMExitDelay.getValue(options); - CompilationWatchDog watchDog = new CompilationWatchDog(compilation, watchedThread, delay, - vmExitDelay, singleShotExecutor, eventHandler); - return watchDog; + return new CompilationWatchDog(compilation, watchedThread, delay, + vmExitDelay, singleShotExecutor, eventHandler, factory); } return null; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java index 768886081f39..3f9e20b9708b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java @@ -428,9 +428,9 @@ private void maybeExitVM(ExceptionAction action) { // Global counters used to measure compilation failure rate over a // period of COMPILATION_FAILURE_DETECTION_PERIOD_MS - private static final GlobalAtomicLong totalCompilations = new GlobalAtomicLong(0L); - private static final GlobalAtomicLong failedCompilations = new GlobalAtomicLong(0L); - private static final GlobalAtomicLong compilationPeriodStart = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong totalCompilations = new GlobalAtomicLong("TOTAL_COMPILATIONS", 0L); + private static final GlobalAtomicLong failedCompilations = new GlobalAtomicLong("FAILED_COMPILATIONS", 0L); + private static final GlobalAtomicLong compilationPeriodStart = new GlobalAtomicLong("COMPILATION_PERIOD_START", 0L); private static final long COMPILATION_FAILURE_DETECTION_PERIOD_NS = TimeUnit.SECONDS.toNanos(2); private static final int MIN_COMPILATIONS_FOR_FAILURE_DETECTION = 25; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.java new file mode 100644 index 000000000000..169e5a6c61ba --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.core.common; + +/** + * Utility to use in a try-with-resource statement override the + * {@linkplain Thread#getContextClassLoader() context class loader} in a scoped way. + */ +public class ContextClassLoaderScope implements AutoCloseable { + private final ClassLoader previous; + private final Thread thread; + + /** + * @param cl the class loader to use as the context class loader for the current thread within + * the scope of this object. If {@code null}, no change to the context class loader + * is made. + */ + public ContextClassLoaderScope(ClassLoader cl) { + thread = Thread.currentThread(); + if (cl != null) { + previous = thread.getContextClassLoader(); + thread.setContextClassLoader(cl); + } else { + previous = null; + } + + } + + @Override + public void close() { + if (previous != null) { + if (thread != Thread.currentThread()) { + throw new IllegalStateException("Cannot (re)set context class loader in a different thread"); + } + thread.setContextClassLoader(previous); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/Fields.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/Fields.java index 0b8dd2fa3ef9..3432a6b5a3b8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/Fields.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/Fields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,16 @@ */ package jdk.graal.compiler.core.common; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.function.Function; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.Edges; import jdk.internal.misc.Unsafe; /** @@ -73,8 +77,35 @@ protected Fields(List fields) { } } + public Field getField(int i) { + try { + return getDeclaringClass(i).getDeclaredField(getName(i)); + } catch (NoSuchFieldException e) { + throw GraalError.shouldNotReachHere(e); + } + } + + /** + * Recomputes the {@link Unsafe} based field offsets and the {@link Edges#getIterationMask()} + * derived from them. + * + * @param getFieldOffset provides the new offsets + * @return a pair (represented as a map entry) where the key is the new offsets and the value is + * the iteration mask + * + */ + public Map.Entry recomputeOffsetsAndIterationMask(Function getFieldOffset) { + long[] newOffsets = new long[offsets.length]; + for (int i = 0; i < offsets.length; i++) { + Field field = getField(i); + long newOffset = getFieldOffset.apply(field); + newOffsets[i] = newOffset; + } + return Map.entry(newOffsets, 0L); + } + public static Fields create(ArrayList fields) { - if (fields.size() == 0) { + if (fields.isEmpty()) { return EMPTY_FIELDS; } return new Fields(fields); @@ -93,15 +124,6 @@ public static void translateInto(Fields fields, ArrayList getType(int index) { return types[index]; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java new file mode 100644 index 000000000000..11f37c45c5da --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.core.common; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import java.io.PrintStream; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.function.Supplier; + +/** + * Service provider interface (SPI) defining support needed by libgraal. Using an SPI instead of + * directly depending on modules such as {@code org.graalvm.nativeimage.libgraal} and + * {@code org.graalvm.jniutils} allows use of jargraal (e.g., putting {@code compiler.jar} on the + * {@code --upgrade-module-path} for use with Truffle on a non-GraalVM JDK) without concern for + * dependencies that are only needed when building libgraal. + */ +public interface LibGraalSupport { + + /** + * Prefix to use for an image runtime system property describing some aspect of the libgraal + * image configuration. These properties are included in the output of + * {@code -Djdk.graal.ShowConfiguration}. + */ + String LIBGRAAL_SETTING_PROPERTY_PREFIX = "libgraal.setting."; + + /** + * Called to signal a fatal, non-recoverable error. This method does not return or throw an + * exception but calls the HotSpot fatal crash routine that produces an hs-err crash log. + * + * @param message a description of the error condition + */ + void fatalError(String message); + + /** + * Performs pre- and post-actions around a libgraal compilation. + */ + AutoCloseable openCompilationRequestScope(); + + /** + * Creates a pre-allocated and pre-initialized word that is off-heap. + * + * @param initialValue the initial value of the off-heap word + * @return a supplier of the address of the off-heap word + */ + @Platforms(Platform.HOSTED_ONLY.class) + Supplier createGlobal(long initialValue); + + /** + * Gets a map from the {@linkplain Class#forName(String) name} of a class to the name of its + * enclosing module. There is one entry in the map for each class loadable via the libgraal + * class loader. + * + * @return an unmodifiable map + */ + Map getClassModuleMap(); + + /** + * Notifies the runtime that the caller is at a point where the live set of objects is expected + * to just have decreased significantly and now is a good time for a partial or full collection. + * + * @param suggestFullGC if a GC will be performed, then suggests a full GC is done. This is true + * when the caller believes the heap occupancy is close to the minimal set of live + * objects for Graal (e.g. after a compilation). + */ + void notifyLowMemoryPoint(boolean suggestFullGC); + + /** + * Enqueues pending {@link Reference}s into their corresponding {@link ReferenceQueue}s and + * executes pending cleaners. + * + * If automatic reference handling is enabled, this method is a no-op. + */ + void processReferences(); + + /** + * Gets the address of the current isolate. + */ + long getIsolateAddress(); + + /** + * Gets an identifier for the current isolate that is guaranteed to be unique for the first + * {@code 2^64 - 1} isolates in the process. + */ + long getIsolateID(); + + /** + * Handles the libgraal options that were parsed. + * + * @param settings libgraal option values + */ + void notifyOptions(EconomicMap settings); + + /** + * Prints the help text for the libgraal options. + * + * @param out where to print + * @param namePrefix prefix to use for each libgraal option name + */ + void printOptions(PrintStream out, String namePrefix); + + /** + * Performs libgraal specific logic when initializing Graal. + */ + void initialize(); + + /** + * Performs libgraal specific logic when shutting down Graal. + * + * @param callbackClassName class name derived from + * {@link jdk.graal.compiler.hotspot.HotSpotGraalCompiler.Options#OnShutdownCallback} + * @param callbackMethodName method name derived from + * {@link jdk.graal.compiler.hotspot.HotSpotGraalCompiler.Options#OnShutdownCallback} + */ + void shutdown(String callbackClassName, String callbackMethodName); + + /** + * Non-null iff accessed in the context of the libgraal class loader or if executing in the + * libgraal runtime. + */ + LibGraalSupport INSTANCE = Init.init(); + + /** + * @return true iff called from classes loaded by the libgraal class loader or if executing in + * the libgraal runtime + */ + static boolean inLibGraal() { + return INSTANCE != null; + } + + class Init { + @SuppressWarnings("try") + static LibGraalSupport init() { + Module module = LibGraalSupport.class.getModule(); + if (module.isNamed()) { + // The named Graal module is not loaded by the libgraal class loader + // and is thus it must have a null LibGraalSupport instance. + return null; + } + try (var ignored = new ContextClassLoaderScope(LibGraalSupport.class.getClassLoader())) { + return ServiceLoader.load(LibGraalSupport.class).findFirst().orElseThrow(() -> new RuntimeException("No provider of " + LibGraalSupport.class.getName() + " service available")); + } + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/BaseTier.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/BaseTier.java index ce1fb43aaff8..d2728dc39d67 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/BaseTier.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/BaseTier.java @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.core.phases; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.TimerKey; @@ -33,7 +34,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.BasePhase; import jdk.graal.compiler.phases.PhaseSuite; -import jdk.graal.compiler.serviceprovider.GraalServices; public class BaseTier extends PhaseSuite { @@ -50,10 +50,17 @@ public LoopPolicies createLoopPolicies(@SuppressWarnings("unused") OptionValues @Override protected void run(StructuredGraph graph, C context) { for (BasePhase phase : getPhases()) { - // Notify the runtime that most objects allocated in previous HIR phase are dead and can - // be reclaimed. This will lower the chance of allocation failure in the next HIR phase. - try (DebugCloseable timer = HIRHintedGC.start(graph.getDebug())) { - GraalServices.notifyLowMemoryPoint(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + /* + * Notify the libgraal runtime that most objects allocated in previous HIR phase are + * dead and can be reclaimed. This will lower the chance of allocation failure in + * the next HIR phase. + */ + try (DebugCloseable timer = HIRHintedGC.start(graph.getDebug())) { + libgraal.notifyLowMemoryPoint(false); + libgraal.processReferences(); + } } phase.apply(graph, context); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugContext.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugContext.java index 46c46d8c7789..58198bbd8d3a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugContext.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugContext.java @@ -56,7 +56,6 @@ import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -87,6 +86,7 @@ public final class DebugContext implements AutoCloseable { */ public static final String DUMP_FILE_MESSAGE_REGEXP = "Dumping debug output to '(?[^']+)'"; + private static final Description DISABLED_DESCRIPTION = new Description(null, "DISABLED_DESCRIPTION"); public static final Description NO_DESCRIPTION = new Description(null, "NO_DESCRIPTION"); public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null; public static final Iterable NO_CONFIG_CUSTOMIZERS = Collections.emptyList(); @@ -350,7 +350,7 @@ public Activation activate() { /** * Singleton used to represent a disabled debug context. */ - private static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, null, NO_GLOBAL_METRIC_VALUES, getDefaultLogStream(), new Immutable(), NO_CONFIG_CUSTOMIZERS); + private static final DebugContext DISABLED = new DebugContext(DISABLED_DESCRIPTION, null, NO_GLOBAL_METRIC_VALUES, getDefaultLogStream(), new Immutable(), NO_CONFIG_CUSTOMIZERS); /** * Create a DebugContext with debugging disabled. @@ -639,6 +639,7 @@ private DebugContext(Description description, Immutable immutable, Iterable factories, boolean disableConfig) { this.immutable = immutable; + this.invariants = Assertions.assertionsEnabled() && description != DISABLED_DESCRIPTION ? new Invariants() : null; this.description = description; this.globalMetrics = globalMetrics; this.compilationListener = compilationListener; @@ -874,11 +875,7 @@ public DebugContext.Scope scope(Object name) { } } - /** - * Arbitrary threads cannot be in the image so null out {@code DebugContext.invariants} which - * holds onto a thread and is only used for assertions. - */ - @NativeImageReinitialize private final Invariants invariants = Assertions.assertionsEnabled() ? new Invariants() : null; + private final Invariants invariants; static StackTraceElement[] getStackTrace(Thread thread) { return thread.getStackTrace(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/GlobalMetrics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/GlobalMetrics.java index 4159ca74c9e2..2e809c94f94c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/GlobalMetrics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/GlobalMetrics.java @@ -88,9 +88,9 @@ private static PrintStream openPrintStream(String metricsFile, Path[] outPath) t } static Path generateFileName(String metricsFile) { - long isolateID = IsolateUtil.getIsolateID(); Path path; - if (isolateID != 0L) { + if (IsolateUtil.getIsolateAddress() != 0L) { + long isolateID = IsolateUtil.getIsolateID(); int lastDot = metricsFile.lastIndexOf('.'); if (lastDot != -1) { path = Paths.get(metricsFile.substring(0, lastDot) + '@' + isolateID + metricsFile.substring(lastDot)); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java index 08f5c1a71eac..6495ca921b36 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java @@ -43,8 +43,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.vm.ci.common.NativeImageReinitialize; -import org.graalvm.nativeimage.ImageInfo; final class IgvDumpChannel implements WritableByteChannel { @@ -93,7 +91,7 @@ void realClose() throws IOException { } } - @NativeImageReinitialize private static boolean networkDumpingUnsupportedWarned; + private static boolean networkDumpingUnsupportedWarned; WritableByteChannel channel() throws IOException { if (closed) { @@ -104,7 +102,7 @@ WritableByteChannel channel() throws IOException { if (target == PrintGraphTarget.File) { sharedChannel = createFileChannel(pathProvider, null); } else if (target == PrintGraphTarget.Network) { - if (ImageInfo.inImageRuntimeCode() && !ENABLE_NETWORK_DUMPING) { + if (GraalServices.isInLibgraal() && !ENABLE_NETWORK_DUMPING) { if (!networkDumpingUnsupportedWarned) { // Ignore races or multiple isolates - an extra warning is ok networkDumpingUnsupportedWarned = true; @@ -147,7 +145,7 @@ private static WritableByteChannel createNetworkChannel(Supplier pathPro } } - @NativeImageReinitialize private static String lastTargetAnnouncement; + private static String lastTargetAnnouncement; private static void maybeAnnounceTarget(String targetAnnouncement) { if (!targetAnnouncement.equals(lastTargetAnnouncement)) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Edges.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Edges.java index 2bea2c5a7c96..d8be19031156 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Edges.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Edges.java @@ -27,11 +27,16 @@ import static jdk.graal.compiler.graph.Graph.isNodeModificationCountsEnabled; import static jdk.graal.compiler.graph.Node.NOT_ITERABLE; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Iterator; +import java.util.Map; +import java.util.function.Function; import jdk.graal.compiler.core.common.Fields; import jdk.graal.compiler.core.common.FieldsScanner; +import jdk.graal.compiler.debug.Assertions; +import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass.EdgeInfo; import jdk.internal.misc.Unsafe; @@ -41,8 +46,35 @@ */ public abstract class Edges extends Fields { + private static final long MAX_EDGES = 8; + private static final long MAX_LIST_EDGES = 6; + static final long OFFSET_MASK = 0xFC; + static final long LIST_MASK = 0x01; + static final long NEXT_EDGE = 0x08; + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + public static long computeIterationMask(Type type, int directCount, long[] offsets) { + long mask = 0; + if (offsets.length > MAX_EDGES) { + throw new GraalError("Exceeded maximum of %d edges (%s)", MAX_EDGES, type); + } + if (offsets.length - directCount > MAX_LIST_EDGES) { + throw new GraalError("Exceeded maximum of %d list edges (%s)", MAX_LIST_EDGES, type); + } + + for (int i = offsets.length - 1; i >= 0; i--) { + long offset = offsets[i]; + assert ((offset & OFFSET_MASK) == offset) : Assertions.errorMessageContext("field offset too large or has low bits set", offset); + mask <<= NEXT_EDGE; + mask |= offset; + if (i >= directCount) { + mask |= 0x3; + } + } + return mask; + } + /** * Constants denoting whether a set of edges are inputs or successors. */ @@ -53,11 +85,20 @@ public enum Type { private final int directCount; private final Type type; + private final long iterationMask; public Edges(Type type, int directCount, ArrayList edges) { super(edges); this.type = type; this.directCount = directCount; + this.iterationMask = computeIterationMask(type, directCount, offsets); + } + + @Override + public Map.Entry recomputeOffsetsAndIterationMask(Function getFieldOffset) { + Map.Entry e = super.recomputeOffsetsAndIterationMask(getFieldOffset); + long[] newOffsets = e.getKey(); + return Map.entry(newOffsets, computeIterationMask(type, directCount, newOffsets)); } public static void translateInto(Edges edges, ArrayList infos) { @@ -66,6 +107,10 @@ public static void translateInto(Edges edges, ArrayList infos) { } } + public long getIterationMask() { + return iterationMask; + } + public static Node getNodeUnsafe(Node node, long offset) { return (Node) UNSAFE.getReference(node, offset); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java index 90261a55a445..df4232c1d1a4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java @@ -28,6 +28,9 @@ import static jdk.graal.compiler.debug.GraalError.shouldNotReachHere; import static jdk.graal.compiler.debug.GraalError.shouldNotReachHereUnexpectedValue; import static jdk.graal.compiler.graph.Edges.translateInto; +import static jdk.graal.compiler.graph.Edges.NEXT_EDGE; +import static jdk.graal.compiler.graph.Edges.LIST_MASK; +import static jdk.graal.compiler.graph.Edges.OFFSET_MASK; import static jdk.graal.compiler.graph.Graph.isNodeModificationCountsEnabled; import static jdk.graal.compiler.graph.InputEdges.translateInto; import static jdk.graal.compiler.graph.Node.WithAllEdges; @@ -94,11 +97,6 @@ public final class NodeClass extends FieldIntrospection { private static final TimerKey Init_AllowedUsages = DebugContext.timer("NodeClass.Init.AllowedUsages"); private static final TimerKey Init_IterableIds = DebugContext.timer("NodeClass.Init.IterableIds"); - public static final long MAX_EDGES = 8; - public static final long MAX_LIST_EDGES = 6; - public static final long OFFSET_MASK = 0xFC; - public static final long LIST_MASK = 0x01; - public static final long NEXT_EDGE = 0x08; private static final int SHORT_INPUT_LIST_THRESHOLD = 3; @SuppressWarnings("try") @@ -160,8 +158,6 @@ public static NodeClass get(Class clazz) { private final int iterableId; private final EnumSet allowedUsageTypes; private int[] iterableIds; - private final long inputsIteration; - private final long successorIteration; private static final CounterKey ITERABLE_NODE_TYPES = DebugContext.counter("IterableNodeTypes"); @@ -200,9 +196,7 @@ private NodeClass(Class clazz, NodeClass superNodeClass, FieldsSca try (DebugCloseable t1 = Init_Edges.start(debug)) { successors = new SuccessorEdges(fs.directSuccessors, fs.successors); - successorIteration = computeIterationMask(successors.type(), successors.getDirectCount(), successors.getOffsets()); inputs = new InputEdges(fs.directInputs, fs.inputs); - inputsIteration = computeIterationMask(inputs.type(), inputs.getDirectCount(), inputs.getOffsets()); } try (DebugCloseable t1 = Init_Data.start(debug)) { data = Fields.create(fs.data); @@ -220,6 +214,7 @@ private NodeClass(Class clazz, NodeClass superNodeClass, FieldsSca NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class, debug); assert info != null : "Missing NodeInfo annotation on " + clazz; + shortName = computeShortName(info); if (!info.nameTemplate().isEmpty()) { this.nameTemplate = info.nameTemplate(); } else if (!info.shortName().isEmpty()) { @@ -308,27 +303,6 @@ public NodeSize size() { return size; } - public static long computeIterationMask(Edges.Type type, int directCount, long[] offsets) { - long mask = 0; - if (offsets.length > NodeClass.MAX_EDGES) { - throw new GraalError("Exceeded maximum of %d edges (%s)", NodeClass.MAX_EDGES, type); - } - if (offsets.length - directCount > NodeClass.MAX_LIST_EDGES) { - throw new GraalError("Exceeded maximum of %d list edges (%s)", NodeClass.MAX_LIST_EDGES, type); - } - - for (int i = offsets.length - 1; i >= 0; i--) { - long offset = offsets[i]; - assert ((offset & OFFSET_MASK) == offset) : Assertions.errorMessageContext("field offset too large or has low bits set", offset); - mask <<= NodeClass.NEXT_EDGE; - mask |= offset; - if (i >= directCount) { - mask |= 0x3; - } - } - return mask; - } - private synchronized void addIterableId(int newIterableId) { assert !containsId(newIterableId, iterableIds); int[] copy = Arrays.copyOf(iterableIds, iterableIds.length + 1); @@ -354,23 +328,23 @@ private static boolean containsId(int iterableId, int[] iterableIds) { return false; } - private String shortName; + private final String shortName; public String shortName() { - if (shortName == null) { - NodeInfo info = getClazz().getAnnotation(NodeInfo.class); - if (!info.shortName().isEmpty()) { - shortName = info.shortName(); + return shortName; + } + + private String computeShortName(NodeInfo info) { + if (!info.shortName().isEmpty()) { + return info.shortName(); + } else { + String localShortName = getClazz().getSimpleName(); + if (localShortName.endsWith("Node") && !localShortName.equals("StartNode") && !localShortName.equals("EndNode")) { + return localShortName.substring(0, localShortName.length() - 4); } else { - String localShortName = getClazz().getSimpleName(); - if (localShortName.endsWith("Node") && !localShortName.equals("StartNode") && !localShortName.equals("EndNode")) { - shortName = localShortName.substring(0, localShortName.length() - 4); - } else { - shortName = localShortName; - } + return localShortName; } } - return shortName; } @Override @@ -422,7 +396,7 @@ public EnumSet getAllowedUsageTypes() { /** * Describes a field representing an input or successor edge in a node. */ - protected static class EdgeInfo extends FieldsScanner.FieldInfo { + public static class EdgeInfo extends FieldsScanner.FieldInfo { public EdgeInfo(long offset, String name, Class type, Class declaringClass) { super(offset, name, type, declaringClass); @@ -1075,7 +1049,7 @@ public final long advanceInput() { int size = nodeList.size(); if (size != 0) { // Set pointer to upper most index of node list. - return ((mask >>> NEXT_EDGE) << 24) | (mask & 0xFD) | ((size - 1) << NEXT_EDGE); + return ((mask >>> NEXT_EDGE) << 24) | (mask & 0xFD) | ((long) (size - 1) << NEXT_EDGE); } } // Node list is empty or null => skip. @@ -1146,7 +1120,7 @@ public Position nextPosition() { } public NodeIterable getSuccessorIterable(final Node node) { - long mask = this.successorIteration; + long mask = this.successors.getIterationMask(); return new NodeIterable<>() { @Override @@ -1180,7 +1154,7 @@ public String toString() { } public NodeIterable getInputIterable(final Node node) { - long mask = this.inputsIteration; + long mask = this.inputs.getIterationMask(); return new NodeIterable<>() { @Override @@ -1214,11 +1188,11 @@ public String toString() { } public boolean equalSuccessors(Node node, Node other) { - return equalEdges(node, other, successorIteration); + return equalEdges(node, other, successors.getIterationMask()); } public boolean equalInputs(Node node, Node other) { - return equalEdges(node, other, inputsIteration); + return equalEdges(node, other, inputs.getIterationMask()); } private boolean equalEdges(Node node, Node other, long mask) { @@ -1245,7 +1219,7 @@ private boolean equalEdges(Node node, Node other, long mask) { } public void pushInputs(Node node, NodeStack stack) { - long myMask = this.inputsIteration; + long myMask = this.inputs.getIterationMask(); while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { @@ -1273,11 +1247,11 @@ private static void pushAllHelper(NodeStack stack, Node node, long offset) { } public void applySuccessors(Node node, EdgeVisitor consumer) { - applyEdges(node, consumer, this.successorIteration, successors); + applyEdges(node, consumer, this.successors.getIterationMask(), successors); } public void applyInputs(Node node, EdgeVisitor consumer) { - applyEdges(node, consumer, this.inputsIteration, inputs); + applyEdges(node, consumer, this.inputs.getIterationMask(), inputs); } private static void applyEdges(Node node, EdgeVisitor consumer, long mask, Edges edges) { @@ -1317,7 +1291,7 @@ private static void applyHelper(Node node, EdgeVisitor consumer, long offset) { } public void unregisterAtSuccessorsAsPredecessor(Node node) { - long myMask = this.successorIteration; + long myMask = this.successors.getIterationMask(); while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { @@ -1347,7 +1321,7 @@ private static void unregisterAtSuccessorsAsPredecessorHelper(Node node, long of } public void registerAtSuccessorsAsPredecessor(Node node) { - long myMask = this.successorIteration; + long myMask = this.successors.getIterationMask(); while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { @@ -1386,7 +1360,7 @@ private static void registerAtSuccessorsAsPredecessorHelper(Node node, long offs */ public boolean replaceFirstInput(Node node, Node key, Node replacement) { assert node.getNodeClass() == this : Assertions.errorMessageContext("node", node, "this", this); - return replaceFirstEdge(node, key, replacement, this.inputsIteration, inputs); + return replaceFirstEdge(node, key, replacement, this.inputs.getIterationMask(), inputs); } /** @@ -1399,7 +1373,7 @@ public boolean replaceFirstInput(Node node, Node key, Node replacement) { */ public boolean replaceFirstSuccessor(Node node, Node key, Node replacement) { assert node.getNodeClass() == this : Assertions.errorMessageContext("node", node, "this", this); - return replaceFirstEdge(node, key, replacement, this.successorIteration, successors); + return replaceFirstEdge(node, key, replacement, this.successors.getIterationMask(), successors); } private static boolean replaceFirstEdge(Node node, Node key, Node replacement, long mask, Edges edges) { @@ -1426,7 +1400,8 @@ private static boolean replaceFirstEdge(Node node, Node key, Node replacement, l } void registerAtInputsAsUsage(Node node) { - long myMask = this.inputsIteration; + // GraalError.guarantee(this.inputsIteration != null, this.getClazz().getName()); + long myMask = this.inputs.getIterationMask(); while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { @@ -1456,7 +1431,7 @@ private static void registerAtInputsAsUsageHelper(Node node, long offset) { } public void unregisterAtInputsAsUsage(Node node) { - long myMask = this.inputsIteration; + long myMask = this.inputs.getIterationMask(); while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index 94f6d84311c2..979383ba0dee 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -31,10 +31,11 @@ import static jdk.graal.compiler.core.GraalCompilerOptions.PrintCompilation; import static jdk.graal.compiler.core.phases.HighTier.Options.Inline; import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsing; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.io.PrintStream; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.options.Option; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -58,13 +59,10 @@ import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.spi.StableProfileProvider; import jdk.graal.compiler.nodes.spi.StableProfileProvider.TypeFilter; -import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionType; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.options.OptionsParser; import jdk.graal.compiler.printer.GraalDebugHandlersFactory; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -80,9 +78,6 @@ public class CompilationTask implements CompilationWatchDog.EventHandler { static class Options { - @Option(help = "Perform a full GC of the libgraal heap after every compile to reduce idle heap and reclaim " + - "references to the HotSpot heap. This flag has no effect in the context of jargraal.", type = OptionType.Debug)// - public static final OptionKey FullGCAfterCompile = new OptionKey<>(false); @Option(help = "Options which are enabled based on the method being compiled. " + "The basic syntax is a MethodFilter option specification followed by a list of options to be set for that compilation. " + "\"MethodFilter:\" is used to distinguish this from normal usage of MethodFilter as option." + @@ -233,7 +228,7 @@ protected ExceptionAction lookupAction(OptionValues values, Throwable cause) { */ private static boolean shouldExitVM(Throwable throwable) { // If not in libgraal, don't exit - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraal()) { return false; } // If assertions are not enabled, don't exit. @@ -492,11 +487,16 @@ public HotSpotCompilationRequestResult runCompilation(OptionValues initialOption public HotSpotCompilationRequestResult runCompilation(DebugContext debug) { try (DebugCloseable a = CompilationTime.start(debug)) { HotSpotCompilationRequestResult result = runCompilation(debug, new HotSpotCompilationWrapper()); - - // Notify the runtime that most objects allocated in the current compilation - // are dead and can be reclaimed. - try (DebugCloseable timer = HintedFullGC.start(debug)) { - GraalServices.notifyLowMemoryPoint(Options.FullGCAfterCompile.getValue(debug.getOptions())); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + /* + * Notify the libgraal runtime that most objects allocated in the current + * compilation are dead and can be reclaimed. + */ + try (DebugCloseable timer = HintedFullGC.start(debug)) { + libgraal.notifyLowMemoryPoint(true); + libgraal.processReferences(); + } } return result; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java similarity index 80% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/CompilerConfig.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java index 70bae2af222e..12f78be1949a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java @@ -22,8 +22,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.hotspot.libgraal; +package jdk.graal.compiler.hotspot; +import java.io.FileOutputStream; +import java.io.PrintStream; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Path; @@ -37,18 +39,14 @@ import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.EncodedSnippets; -import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; -import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; -import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.hotspot.SymbolicSnippetEncoder; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; import jdk.graal.compiler.util.ObjectCopier; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * A command line program that initializes the compiler data structures to be serialized into the @@ -61,6 +59,7 @@ * {@link jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.Stubs#initStubs} *
*/ +@Platforms(Platform.HOSTED_ONLY.class) public class CompilerConfig { /** @@ -74,7 +73,7 @@ public static void main(String[] args) throws Exception { HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) hostProviders.getReplacements(); OptionValues options = graalRuntime.getCapability(OptionValues.class); - List foreignCallSignatures = getForeignCallSignatures(replacements, options, graalRuntime); + List foreignCallSignatures = getForeignCallSignatures(replacements, options); EncodedSnippets encodedSnippets = getEncodedSnippets(replacements, options); List externalValueFields = ObjectCopier.getExternalValueFields(); @@ -82,20 +81,21 @@ public static void main(String[] args) throws Exception { encodedObjects.put("encodedSnippets", encodedSnippets); encodedObjects.put("foreignCallSignatures", foreignCallSignatures); - ObjectCopier.Encoder encoder = new ObjectCopier.Encoder(externalValueFields) { - @Override - protected ClassInfo makeClassInfo(Class declaringClass) { - ClassInfo ci = ClassInfo.of(declaringClass); - for (var f : ci.fields().values()) { - // Avoid problems with identity hash codes - GraalError.guarantee(!f.getName().toLowerCase(Locale.ROOT).contains("hash"), "Cannot serialize hash field: %s", f); + try (PrintStream debugStream = new PrintStream(new FileOutputStream(args[1]))) { + ObjectCopier.Encoder encoder = new ObjectCopier.Encoder(externalValueFields, debugStream) { + @Override + protected ClassInfo makeClassInfo(Class declaringClass) { + ClassInfo ci = ClassInfo.of(declaringClass); + for (var f : ci.fields().values()) { + // Avoid problems with identity hash codes + GraalError.guarantee(!f.getName().toLowerCase(Locale.ROOT).contains("hash"), "Cannot serialize hash field: %s", f); + } + return ci; } - return ci; - } - }; - byte[] encoded = ObjectCopier.encode(encoder, encodedObjects); - - Files.write(Path.of(args[0]), encoded); + }; + byte[] encoded = ObjectCopier.encode(encoder, encodedObjects); + Files.write(Path.of(args[0]), encoded); + } } private static EncodedSnippets getEncodedSnippets(HotSpotReplacementsImpl replacements, OptionValues options) { @@ -103,18 +103,17 @@ private static EncodedSnippets getEncodedSnippets(HotSpotReplacementsImpl replac return snippetEncoder.encodeSnippets(options); } - private static List getForeignCallSignatures(HotSpotReplacementsImpl replacements, OptionValues options, HotSpotGraalRuntimeProvider graalRuntime) { + private static List getForeignCallSignatures(HotSpotReplacementsImpl replacements, OptionValues options) { List sigs = new ArrayList<>(); EconomicMap foreignCalls = collectForeignCalls(replacements, options); MapCursor cursor = foreignCalls.getEntries(); while (cursor.advance()) { - ForeignCallSignature sig = cursor.getKey(); + sigs.add(cursor.getKey()); HotSpotForeignCallLinkage linkage = cursor.getValue(); - sigs.add(sig); - if (linkage != null) { - // Construct the stub so that all types it uses are registered in + if (linkage != null && linkage.isCompiledStub()) { + // Construct the stub graph so that all types it uses are registered in // SymbolicSnippetEncoder.snippetTypes - linkage.finalizeAddress(graalRuntime.getHostBackend()); + linkage.getStub().findTypesInGraph(); } } return sigs; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfigurationFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfigurationFactory.java index a46c237bc88d..d9c252eea4a8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfigurationFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfigurationFactory.java @@ -25,6 +25,7 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.graal.compiler.core.common.LibGraalSupport.LIBGRAAL_SETTING_PROPERTY_PREFIX; import java.util.ArrayList; import java.util.Collections; @@ -203,7 +204,7 @@ private static List getAllCandidates() { } // Ensures ShowConfiguration output is printed once per VM process. - private static final GlobalAtomicLong shownConfiguration = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong shownConfiguration = new GlobalAtomicLong("SHOWN_CONFIGURATION", 0L); /** * Selects and instantiates a {@link CompilerConfigurationFactory}. The selection algorithm is @@ -275,31 +276,24 @@ public static CompilerConfigurationFactory selectFactory(String name, OptionValu */ private Object getLoadedFromLocation(boolean verbose) { if (ImageInfo.inImageRuntimeCode()) { - if (nativeImageLocationQualifier != null) { - return "a " + nativeImageLocationQualifier + " Native Image shared library"; + String justification = "properties initialized via org.graalvm.nativeimage.hosted.RuntimeSystemProperties " + + "are not accessible via GraalServices.getSavedProperties()"; + String settings = GraalServices.getSystemProperties(justification).entrySet().stream()// + .filter(e -> e.getKey().toString().startsWith(LIBGRAAL_SETTING_PROPERTY_PREFIX))// + .map(e -> { + String key = e.getKey().toString().substring(LIBGRAAL_SETTING_PROPERTY_PREFIX.length()); + String val = e.getValue().toString(); + return val.isEmpty() ? key : key + "=" + val; + })// + .collect(Collectors.joining(", ")); + if (!settings.isEmpty()) { + return "a Native Image shared library (" + settings + ")"; } return "a Native Image shared library"; } return verbose ? getClass().getResource(getClass().getSimpleName() + ".class") : "class files"; } - private static String nativeImageLocationQualifier; - - /** - * Gets the qualifier for the libgraal library (e.g., "PGO optimized"). - */ - public static String getNativeImageLocationQualifier() { - return nativeImageLocationQualifier; - } - - /** - * Records a qualifier for the libgraal library (e.g., "PGO optimized"). - */ - public static void setNativeImageLocationQualifier(String s) { - GraalError.guarantee(nativeImageLocationQualifier == null, "Native image location qualifier is already set to %s", nativeImageLocationQualifier); - nativeImageLocationQualifier = s; - } - private static void printConfigInfo(CompilerConfigurationFactory factory) { Object location = factory.getLoadedFromLocation(false); TTY.printf("Using \"%s\" loaded from %s%n", factory.info, location); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index c0841dc7d39e..ad5baecba878 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -25,6 +25,7 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; +import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; import static org.graalvm.nativeimage.ImageInfo.inImageCode; import jdk.graal.compiler.bytecode.BytecodeProvider; @@ -201,7 +202,9 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, bytecodeProvider); providers = replacements.getProviders(); - replacements.maybeInitializeEncoder(); + if (inImageBuildtimeCode()) { + replacements.maybeInitializeEncoder(); + } } GraphBuilderConfiguration.Plugins plugins; try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java index 5f000ac77bd6..122efa543d07 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -372,7 +372,7 @@ private static GlobalAtomicLong getStubData(ForeignCallSignature sig) { synchronized (STUBS) { data = STUBS.get(sig); if (data == null) { - data = new GlobalAtomicLong(0L); + data = new GlobalAtomicLong("STUB_" + sig.getName(), 0L); STUBS.put(sig, data); } } @@ -401,7 +401,7 @@ public static void initStubs(List sigs) { */ public static boolean initStub(ForeignCallSignature sig) { if (!STUBS.containsKey(sig)) { - STUBS.put(sig, new GlobalAtomicLong(0L)); + STUBS.put(sig, new GlobalAtomicLong("STUB_" + sig.getName(), 0L)); return true; } return false; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompiler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompiler.java index 55495b020b46..2aca48f15374 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompiler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompiler.java @@ -30,12 +30,14 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.concurrent.ThreadFactory; import jdk.graal.compiler.api.runtime.GraalJVMCICompiler; import jdk.graal.compiler.code.CompilationResult; import jdk.graal.compiler.core.CompilationWatchDog; import jdk.graal.compiler.core.GraalCompiler; import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.util.CompilationAlarm; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.DebugContext; @@ -63,7 +65,6 @@ import jdk.graal.compiler.phases.tiers.Suites; import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; -import jdk.graal.compiler.serviceprovider.VMSupport; import jdk.internal.misc.Unsafe; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; @@ -77,7 +78,6 @@ import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; import jdk.vm.ci.runtime.JVMCICompiler; -import org.graalvm.nativeimage.ImageInfo; public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable, JVMCICompilerShadow, GraalCompiler.RequestedCrashHandler { @@ -128,7 +128,8 @@ public HotSpotGraalRuntimeProvider getGraalRuntime() { @SuppressWarnings("try") @Override public CompilationRequestResult compileMethod(CompilationRequest request) { - try (AutoCloseable ignored = VMSupport.getCompilationRequestScope()) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { return compileMethod(request, true, getGraalRuntime().getOptions()); } catch (Exception e) { return HotSpotCompilationRequestResult.failure(e.toString(), false); @@ -139,7 +140,7 @@ public CompilationRequestResult compileMethod(CompilationRequest request) { public CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) { try (CompilationContext scope = HotSpotGraalServices.openLocalCompilationContext(request)) { if (graalRuntime.isShutdown()) { - return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true); + return HotSpotCompilationRequestResult.failure("Shutdown entered", true); } ResolvedJavaMethod method = request.getMethod(); @@ -160,10 +161,12 @@ public CompilationRequestResult compileMethod(CompilationRequest request, boolea OptionValues options = task.filterOptions(initialOptions); HotSpotVMConfigAccess config = new HotSpotVMConfigAccess(graalRuntime.getVMConfig().getStore()); - boolean oneIsolatePerCompilation = ImageInfo.inImageRuntimeCode() && + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + boolean oneIsolatePerCompilation = libgraal != null && config.getFlag("JVMCIThreadsPerNativeLibraryRuntime", Integer.class, 0) == 1 && config.getFlag("JVMCICompilerIdleDelay", Integer.class, 1000) == 0; - try (CompilationWatchDog w1 = CompilationWatchDog.watch(task.getCompilationIdentifier(), options, oneIsolatePerCompilation, task); + ThreadFactory factory = libgraal != null ? HotSpotGraalServiceThread::new : null; + try (CompilationWatchDog w1 = CompilationWatchDog.watch(task.getCompilationIdentifier(), options, oneIsolatePerCompilation, task, factory); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { if (compilationCounters != null) { @@ -368,11 +371,12 @@ public boolean isGCSupported(int gcIdentifier) { } // Support for CrashAtThrowsOOME - private static final GlobalAtomicLong OOME_CRASH_DONE = new GlobalAtomicLong(0); + private static final GlobalAtomicLong OOME_CRASH_DONE = new GlobalAtomicLong("OOME_CRASH_DONE", 0); @Override public boolean notifyCrash(OptionValues options, String crashMessage) { - if (ImageInfo.inImageRuntimeCode()) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { if (HotSpotGraalCompiler.Options.CrashAtThrowsOOME.getValue(options)) { if (OOME_CRASH_DONE.compareAndSet(0L, 1L)) { // The -Djdk.libgraal.Xmx option should also be employed to make @@ -386,7 +390,13 @@ public boolean notifyCrash(OptionValues options, String crashMessage) { } else { int crashAtIsFatal = HotSpotGraalCompiler.Options.CrashAtIsFatal.getValue(options); if (crashAtIsFatal != 0) { - VMSupport.fatalError(crashMessage, crashAtIsFatal); + try { + Thread.sleep(crashAtIsFatal); + } catch (InterruptedException e) { + // ignore + } + libgraal.fatalError(crashMessage); + // If changing this message, update the test for it in mx_vm_gate.py System.out.println("CrashAtIsFatal: no fatalError function pointer installed"); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java index 91c038efbfb8..d158ef846d43 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -49,7 +49,6 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; -import jdk.vm.ci.services.Services; public final class HotSpotGraalCompilerFactory implements JVMCICompilerFactory { @@ -173,10 +172,6 @@ public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { // is true so verify that here. throw new GraalError("Invariant violation: inImageBuildtimeCode && inImageRuntimeCode must not both be true"); } - if (Services.IS_BUILDING_NATIVE_IMAGE && Services.IS_IN_NATIVE_IMAGE) { - // Same check as above but for the JVMCI equivalent properties. - throw new GraalError("Invariant violation: IS_BUILDING_NATIVE_IMAGE && IS_IN_NATIVE_IMAGE must not both be true"); - } HotSpotJVMCIRuntime hsRuntime = (HotSpotJVMCIRuntime) runtime; checkUnsafeAccess(hsRuntime); ensureInitialized(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java index 576fb3b3c227..bb77e7a29ea7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java @@ -26,7 +26,6 @@ import jdk.graal.compiler.serviceprovider.ServiceProvider; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.hotspot.HotSpotVMEventListener; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.services.JVMCIServiceLocator; @@ -59,8 +58,8 @@ T getProvider(Class service, HotSpotGraalJVMCIServiceLocator locator) { return null; } - @NativeImageReinitialize private HotSpotGraalRuntime graalRuntime; - @NativeImageReinitialize private HotSpotGraalVMEventListener vmEventListener; + private HotSpotGraalRuntime graalRuntime; + private HotSpotGraalVMEventListener vmEventListener; /** * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java index 5fe1a4b4a3be..9a53f9694780 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java @@ -27,10 +27,9 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.io.PrintStream; -import java.util.HashMap; import java.util.Map; -import java.util.Set; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; import jdk.graal.compiler.serviceprovider.GraalServices; import org.graalvm.collections.EconomicMap; @@ -41,7 +40,7 @@ import jdk.graal.compiler.options.OptionsParser; import jdk.vm.ci.common.InitTimer; -import jdk.vm.ci.common.NativeImageReinitialize; +import org.graalvm.collections.EconomicSet; /** * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The @@ -68,12 +67,10 @@ public class HotSpotGraalOptionValues { */ public static final String LIBGRAAL_VM_OPTION_PROPERTY_PREFIX = "jdk.graal.internal."; - private static final Set UNSUPPORTED_LIBGRAAL_PREFIXES = Set.of("jdk.libgraal.", "libgraal."); - /** * Guard for issuing warning about deprecated Graal option prefix at most once. */ - private static final GlobalAtomicLong LEGACY_OPTION_DEPRECATION_WARNED = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong LEGACY_OPTION_DEPRECATION_WARNED = new GlobalAtomicLong("LEGACY_OPTION_DEPRECATION_WARNED", 0L); /** * Gets the system property assignment that would set the current value for a given option. @@ -82,7 +79,7 @@ public static String asSystemPropertySetting(OptionValues options, OptionKey return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options); } - @NativeImageReinitialize private static volatile OptionValues hotspotOptions; + private static volatile OptionValues hotspotOptions; public static OptionValues defaultOptions() { OptionValues res = hotspotOptions; @@ -112,8 +109,7 @@ public static EconomicMap, Object> parseOptions() { Map savedProps = GraalServices.getSavedProperties(); EconomicMap compilerOptionSettings = EconomicMap.create(); - // Need to use Map as it's a shared type between guest and host in LibGraal. - Map vmOptionSettings = new HashMap<>(); + EconomicMap vmOptionSettings = EconomicMap.create(); for (Map.Entry e : savedProps.entrySet()) { String name = e.getKey(); @@ -139,20 +135,16 @@ public static EconomicMap, Object> parseOptions() { String value = e.getValue(); compilerOptionSettings.put(stripPrefix(name, GRAAL_OPTION_PROPERTY_PREFIX), value); } - } else { - for (var prefix : UNSUPPORTED_LIBGRAAL_PREFIXES) { - if (name.startsWith(prefix)) { - String baseName = name.substring(prefix.length()); - String msg = String.format("The '%s' property prefix is no longer supported. Use %s%s instead of %s%s.", - prefix, LIBGRAAL_VM_OPTION_PROPERTY_PREFIX, baseName, prefix, baseName); - throw new IllegalArgumentException(msg); - } - } } } if (!vmOptionSettings.isEmpty()) { - notifyLibgraalOptions(vmOptionSettings); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + libgraal.notifyOptions(vmOptionSettings); + } else { + System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", vmOptionSettings); + } } OptionsParser.parseOptions(compilerOptionSettings, compilerOptionValues, descriptors); return compilerOptionValues; @@ -168,13 +160,9 @@ private static String stripPrefix(String name, String prefix) { } /** - * Substituted by {@code Target_jdk_graal_compiler_hotspot_HotSpotGraalOptionValues}. - * - * @param settings unparsed libgraal option values + * The set of libgraal options seen on the command line. */ - private static void notifyLibgraalOptions(Map settings) { - System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", String.join(", ", settings.keySet())); - } + static EconomicSet explicitOptions = EconomicSet.create(); private static OptionValues initializeOptions() { EconomicMap, Object> values = parseOptions(); @@ -188,17 +176,9 @@ private static OptionValues initializeOptions() { static void printProperties(OptionValues compilerOptions, PrintStream out) { boolean all = HotSpotGraalCompilerFactory.Options.PrintPropertiesAll.getValue(compilerOptions); compilerOptions.printHelp(OptionsParser.getOptionsLoader(), out, GRAAL_OPTION_PROPERTY_PREFIX, all); - if (all) { - printLibgraalProperties(out, LIBGRAAL_VM_OPTION_PROPERTY_PREFIX); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (all && libgraal != null) { + libgraal.printOptions(out, LIBGRAAL_VM_OPTION_PROPERTY_PREFIX); } } - - /** - * Substituted by {@code Target_jdk_graal_compiler_hotspot_HotSpotGraalOptionValues}. - * - * @param out where help is to be printed - * @param prefix system property prefix for libgraal VM options - */ - private static void printLibgraalProperties(PrintStream out, String prefix) { - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java index ea73421d8dd4..fdfc96aa7eda 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java @@ -35,7 +35,7 @@ import java.util.Map; import java.util.function.Predicate; -import org.graalvm.nativeimage.ImageInfo; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; @@ -67,7 +67,6 @@ import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.serviceprovider.JavaVersionUtil; -import jdk.graal.compiler.serviceprovider.VMSupport; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.stack.StackIntrospection; import jdk.vm.ci.common.InitTimer; @@ -194,7 +193,10 @@ public GlobalMetrics getMetricValues() { this.compilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); - VMSupport.startupLibGraal(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + libgraal.initialize(); + } } /** @@ -420,18 +422,20 @@ synchronized void shutdown() { outputDirectory.close(); - if (ImageInfo.inImageRuntimeCode()) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { String callback = HotSpotGraalCompiler.Options.OnShutdownCallback.getValue(options); + String callbackClassName = null; + String callbackMethodName = null; if (callback != null) { int lastDot = callback.lastIndexOf('.'); if (lastDot < 1 || lastDot == callback.length() - 1) { throw new IllegalArgumentException(HotSpotGraalCompiler.Options.OnShutdownCallback.getName() + " value does not have . format: " + callback); } - String cbClassName = callback.substring(0, lastDot); - String cbMethodName = callback.substring(lastDot + 1); - VMSupport.invokeShutdownCallback(cbClassName, cbMethodName); + callbackClassName = callback.substring(0, lastDot); + callbackMethodName = callback.substring(lastDot + 1); } - VMSupport.shutdownLibGraal(); + libgraal.shutdown(callbackClassName, callbackMethodName); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/GraalServiceThread.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java similarity index 72% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/GraalServiceThread.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java index 7c5f25485341..ef87b6b285a2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/GraalServiceThread.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java @@ -22,27 +22,30 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.core; +package jdk.graal.compiler.hotspot; import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; /** - * This is a utility class for Threads started by the compiler itself. In certain execution - * environments extra work must be done for these threads to execute correctly and this class - * provides hooks for this work. + * This is a utility class for Threads started by the compiler itself. In libgraal, such threads + * must be attached and detached to the host JVM process. */ -public class GraalServiceThread extends Thread { +public class HotSpotGraalServiceThread extends Thread { private final Runnable runnable; - public GraalServiceThread(String name, Runnable runnable) { - super(name); + public HotSpotGraalServiceThread(Runnable runnable) { this.runnable = runnable; } @Override public final void run() { try { - beforeRun(); + if (GraalServices.isInLibgraal()) { + if (!HotSpotJVMCIRuntime.runtime().attachCurrentThread(isDaemon(), null)) { + throw new InternalError("Couldn't attach to HotSpot runtime"); + } + } } catch (InternalError t) { // There was a problem attaching this thread to the libgraal peer runtime. // Not much that can be done apart from terminating the thread. @@ -52,7 +55,9 @@ public final void run() { try { runnable.run(); } finally { - afterRun(); + if (GraalServices.isInLibgraal()) { + HotSpotJVMCIRuntime.runtime().detachCurrentThread(false); + } } } @@ -60,27 +65,14 @@ public final void run() { * Notifies of an error on attaching this thread to the libgraal peer runtime. * * The default implementation of this method is to print the stack trace for {@code error} if - * the {@code GraalServiceThread.verbose} system property is {@code "true"}. + * the {@code HotSpotGraalServiceThread.verbose} system property is {@code "true"}. * * @param error the error */ protected void onAttachError(InternalError error) { - if (Boolean.parseBoolean(GraalServices.getSavedProperty("GraalServiceThread.verbose", "false"))) { + if (Boolean.parseBoolean(GraalServices.getSavedProperty("HotSpotGraalServiceThread.verbose", "false"))) { error.printStackTrace(); } } - /** - * Substituted by {@code Target_jdk_graal_compiler_core_GraalServiceThread} to attach to the - * peer runtime if required. - */ - private void afterRun() { - } - - /** - * Substituted by {@code Target_jdk_graal_compiler_core_GraalServiceThread} to attach to the - * peer runtime if required. - */ - private void beforeRun() { - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotMarkId.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotMarkId.java index 0dbf1371b059..9f6d49f5884b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotMarkId.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotMarkId.java @@ -27,7 +27,6 @@ import jdk.graal.compiler.code.CompilationResult; import jdk.graal.compiler.debug.GraalError; -import jdk.vm.ci.common.NativeImageReinitialize; /** * Constants used to mark special positions in code being installed into the code cache by Graal C++ @@ -72,7 +71,7 @@ public enum HotSpotMarkId implements CompilationResult.MarkId { Z_BARRIER_RELOCATION_FORMAT_STORE_GOOD_BEFORE_MOV("aarch64"), Z_BARRIER_RELOCATION_FORMAT_STORE_BAD_BEFORE_MOV("aarch64"); - @NativeImageReinitialize private Integer value; + private Integer value; private final String arch; HotSpotMarkId() { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 1ed9fd3af364..976ec5afc0d7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -60,10 +60,11 @@ import jdk.graal.compiler.replacements.IntrinsicGraphBuilder; import jdk.graal.compiler.replacements.ReplacementsImpl; import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * Filters certain method substitutions based on whether there is underlying hardware support for @@ -72,11 +73,17 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl { public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider bytecodeProvider, TargetDescription target) { super(new GraalDebugHandlersFactory(providers.getSnippetReflection()), providers, bytecodeProvider, target); + if (inImageBuildtimeCode()) { + registeredSnippets = EconomicSet.create(); + } } HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(new GraalDebugHandlersFactory(replacements.getProviders().getSnippetReflection()), providers, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); + if (inImageBuildtimeCode()) { + registeredSnippets = EconomicSet.create(); + } } @Override @@ -84,15 +91,11 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } + @Platforms(Platform.HOSTED_ONLY.class) public SymbolicSnippetEncoder maybeInitializeEncoder() { - if (inImageRuntimeCode()) { - return null; - } - if (inImageBuildtimeCode()) { - synchronized (HotSpotReplacementsImpl.class) { - if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this); - } + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); } } return snippetEncoder; @@ -185,18 +188,18 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo // When assertions are enabled, these fields are used to ensure all snippets are // registered during Graal initialization which in turn ensures that native image // building will not miss any snippets. - @NativeImageReinitialize private EconomicSet registeredSnippets = EconomicSet.create(); + @Platforms(Platform.HOSTED_ONLY.class)// + private EconomicSet registeredSnippets; + @Platforms(Platform.HOSTED_ONLY.class)// private boolean snippetRegistrationClosed; @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (!inImageRuntimeCode()) { + if (inImageBuildtimeCode()) { assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { - if (inImageBuildtimeCode()) { - snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); - } + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); } } } @@ -219,7 +222,9 @@ public boolean isSnippet(ResolvedJavaMethod method) { @Override public void closeSnippetRegistration() { - snippetRegistrationClosed = true; + if (inImageBuildtimeCode()) { + snippetRegistrationClosed = true; + } } public static EncodedSnippets getEncodedSnippets() { @@ -229,30 +234,20 @@ public static EncodedSnippets getEncodedSnippets() { return encodedSnippets; } + @Platforms(Platform.HOSTED_ONLY.class)// public static boolean snippetsAreEncoded() { return encodedSnippets != null; } - public void clearSnippetParameterNames() { - assert snippetEncoder != null; - snippetEncoder.clearSnippetParameterNames(); - } - + @Platforms(Platform.HOSTED_ONLY.class)// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; } - public boolean encode(OptionValues options) { - SymbolicSnippetEncoder encoder = snippetEncoder; - if (encoder != null) { - return encoder.encode(options); - } - return false; - } - private static volatile EncodedSnippets encodedSnippets; - @NativeImageReinitialize private static SymbolicSnippetEncoder snippetEncoder; + @Platforms(Platform.HOSTED_ONLY.class)// + private static SymbolicSnippetEncoder snippetEncoder; @SuppressWarnings("try") @Override @@ -270,7 +265,7 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } } - assert registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); + assert !inImageBuildtimeCode() || registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); } @@ -283,6 +278,7 @@ public T getInjectedArgument(Class capability) { return super.getInjectedArgument(capability); } + @Platforms(Platform.HOSTED_ONLY.class) public ResolvedJavaMethod findSnippetMethod(ResolvedJavaMethod thisMethod) { if (snippetEncoder == null) { throw new GraalError("findSnippetMethod called before initialization of Replacements"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotTTYStreamProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotTTYStreamProvider.java index 1b66967ff3fd..6828310acbfe 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotTTYStreamProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotTTYStreamProvider.java @@ -43,7 +43,6 @@ import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.serviceprovider.IsolateUtil; import jdk.graal.compiler.serviceprovider.ServiceProvider; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @ServiceProvider(TTYStreamProvider.class) @@ -74,7 +73,7 @@ public PrintStream getStream() { /** * Gets a pointer to a global word initialized to 0. */ - private static final GlobalAtomicLong BARRIER = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong BARRIER = new GlobalAtomicLong("BARRIER", 0L); /** * Executes {@code action}. {@link #BARRIER} is used to ensure the action is executed exactly @@ -154,7 +153,7 @@ private static String makeFilename(String nameTemplate) { * initialization. */ class DelayedOutputStream extends OutputStream { - @NativeImageReinitialize private volatile OutputStream lazy; + private volatile OutputStream lazy; private OutputStream lazy() { if (lazy == null) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetSignature.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetSignature.java index 7ab6f7e0685b..95463aa81bd5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetSignature.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetSignature.java @@ -29,7 +29,6 @@ import java.util.List; import jdk.graal.compiler.util.SignatureUtil; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; @@ -49,7 +48,7 @@ public final class SnippetSignature implements Signature { private final String returnType; private final String originalString; - @NativeImageReinitialize private static EnumMap primitiveTypes = null; + private static EnumMap primitiveTypes = null; static synchronized void initPrimitiveKindCache(MetaAccessProvider metaAccess) { if (primitiveTypes == null) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java index 4c00b133d5f7..66ec39e0ba19 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java @@ -42,7 +42,6 @@ import java.util.Set; import java.util.function.BiFunction; -import jdk.graal.compiler.serviceprovider.GraalServices; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; @@ -137,14 +136,17 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.UnresolvedJavaType; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * This class performs graph encoding using {@link GraphEncoder} but also converts JVMCI type and * method references into a symbolic form that can be resolved at graph decode time using * {@link SymbolicJVMCIReference}. *

- * An instance of this class only exist when {@link GraalServices#isBuildingLibgraal()} is true. + * An instance of this class only exist when building libgraal. */ +@Platforms(Platform.HOSTED_ONLY.class) public class SymbolicSnippetEncoder { /** @@ -218,12 +220,6 @@ void addDelayedInvocationPluginMethod(ResolvedJavaMethod method) { delayedInvocationPluginMethods.add(method); } - public void clearSnippetParameterNames() { - for (SnippetParameterInfo info : snippetParameterInfos.getValues()) { - info.clearNames(); - } - } - protected class SnippetInlineInvokePlugin implements InlineInvokePlugin { @Override @@ -541,7 +537,7 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic graphDatas.put(keyString, data); } - // Ensure a few types are available + // Ensure a few well known types are available lookupSnippetType(GraalHotSpotVMConfig.class); lookupSnippetType(NamedLocationIdentity.class); lookupSnippetType(SnippetTemplate.EagerSnippetInfo.class); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java index cbc47d2d36b2..2f2bf07b1fce 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java @@ -39,7 +39,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import jdk.graal.compiler.core.GraalServiceThread; import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.graal.compiler.debug.CSVUtil; import jdk.graal.compiler.debug.GraalError; @@ -468,7 +467,7 @@ protected void patternFound(int index) { if (ImageInfo.inImageRuntimeCode()) { throw new GraalError("Use of %s is only supported in jargraal", Options.TimedDynamicCounters.getName()); } - Thread thread = new GraalServiceThread(BenchmarkCounters.class.getSimpleName(), new Runnable() { + Thread thread = new Thread(new Runnable() { long lastTime = System.nanoTime(); @Override @@ -486,6 +485,7 @@ public void run() { } } }); + thread.setName(BenchmarkCounters.class.getSimpleName()); thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java deleted file mode 100644 index 73a78c88da87..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal; - -import static java.lang.invoke.MethodType.methodType; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import jdk.graal.compiler.core.ArchitectureSpecific; -import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.debug.TTY; -import jdk.graal.compiler.graph.NodeClass; -import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; -import jdk.graal.compiler.hotspot.EncodedSnippets; -import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.options.OptionDescriptor; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionsParser; -import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.graal.compiler.util.ObjectCopier; -import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.services.JVMCIServiceLocator; - -/** - * This class is used at image build-time when a libgraal image gets built. Its static methods are - * called from {@code com.oracle.svm.graal.hotspot.libgraal.LibGraalFeature} before static analysis. - * These methods ensure the static field state of Graal and JVMCI classes loaded by the - * LibGraalClassLoader is set up correctly for getting built into libgraal. - */ -@Platforms(Platform.HOSTED_ONLY.class) -public class BuildTime { - - private static final String VALID_LOADER_NAME = "LibGraalClassLoader"; - private static final ClassLoader LOADER = BuildTime.class.getClassLoader(); - - /** - * Creates and registers the data structures used for looking up libgraal compiler options and - * determining which of them are enterprise options. - */ - @SuppressWarnings("unused") - public static Object initLibgraalOptions() { - return OptionsParser.setLibgraalOptions(OptionsParser.LibGraalOptionsInfo.create()); - } - - /** - * Processes the entries in {@code optionObjects} and adds their - * {@linkplain OptionDescriptor#isServiceLoaded() non-service loaded} descriptors to - * {@code descriptorsObject}. - * - * @param optionObjects a list of {@link OptionKey} objects - * @param optionsInfoObject the value returned by {@link #initLibgraalOptions()} - * @param modules unmodifiable map from the {@linkplain Class#forName(String) name} of a class - * to the name of its enclosing module. - * @return the {@link OptionDescriptor} objects added to {@code descriptorsObject} - */ - @SuppressWarnings("unused") - public static Iterable finalizeLibgraalOptions(List optionObjects, Object optionsInfoObject, Map modules) { - GraalError.guarantee(VALID_LOADER_NAME.equals(LOADER.getName()), - "Only call this method from classloader " + VALID_LOADER_NAME); - OptionsParser.LibGraalOptionsInfo optionsInfo = (OptionsParser.LibGraalOptionsInfo) optionsInfoObject; - for (Object optionObject : optionObjects) { - OptionKey option = (OptionKey) optionObject; - OptionDescriptor descriptor = option.getDescriptor(); - if (descriptor.isServiceLoaded()) { - String name = option.getName(); - optionsInfo.descriptors().put(name, descriptor); - String module = modules.get(descriptor.getDeclaringClass().getName()); - if (module.contains("enterprise")) { - optionsInfo.enterpriseOptions().add(name); - } - } - } - return optionsInfo.descriptors().getValues(); - } - - @SuppressWarnings("unused") - public static long[] getInputEdgesOffsets(Object rawNodeClass) { - /* Used by LibGraalFieldsOffsetsFeature.IterationMaskRecomputation */ - NodeClass nodeclass = (NodeClass) rawNodeClass; - return nodeclass.getInputEdges().getOffsets(); - } - - @SuppressWarnings("unused") - public static long[] getSuccessorEdgesOffsets(Object rawNodeClass) { - /* Used by LibGraalFieldsOffsetsFeature.IterationMaskRecomputation */ - NodeClass nodeclass = (NodeClass) rawNodeClass; - return nodeclass.getSuccessorEdges().getOffsets(); - } - - @SuppressWarnings("unchecked") - private static void addProviders(Map, List> services, String arch, Class service) { - List providers = (List) services.computeIfAbsent(service, key -> new ArrayList<>()); - for (Object provider : ServiceLoader.load(service, LOADER)) { - if (provider instanceof ArchitectureSpecific as && !as.getArchitecture().equals(arch)) { - // Skip provider for another architecture - continue; - } - providers.add(provider); - } - } - - /** - * Configures the static state needed for libgraal. - * - * @param arch a value compatible with {@link ArchitectureSpecific#getArchitecture()} - */ - @SuppressWarnings({"try", "unused", "unchecked"}) - public static void configureGraalForLibGraal(String arch, - List> guestServiceClasses, - Consumer> registerAsInHeap, - String nativeImageLocationQualifier, - byte[] encodedGuestObjects) { - GraalError.guarantee(VALID_LOADER_NAME.equals(LOADER.getName()), - "Only call this method from classloader " + VALID_LOADER_NAME); - - Map, List> services = new HashMap<>(); - guestServiceClasses.forEach(c -> addProviders(services, arch, c)); - GraalServices.setLibgraalServices(services); - - CompilerConfigurationFactory.setNativeImageLocationQualifier(nativeImageLocationQualifier); - - try { - Field cachedHotSpotJVMCIBackendFactoriesField = ObjectCopier.getField(HotSpotJVMCIRuntime.class, "cachedHotSpotJVMCIBackendFactories"); - GraalError.guarantee(cachedHotSpotJVMCIBackendFactoriesField.get(null) == null, "Expect cachedHotSpotJVMCIBackendFactories to be null"); - ServiceLoader load = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, LOADER); - List backendFactories = load.stream()// - .map(ServiceLoader.Provider::get)// - .filter(s -> s.getArchitecture().equals(arch))// - .toList(); - cachedHotSpotJVMCIBackendFactoriesField.set(null, backendFactories); - GraalError.guarantee(backendFactories.size() == 1, "%s", backendFactories); - - var jvmciServiceLocatorCachedLocatorsField = ObjectCopier.getField(JVMCIServiceLocator.class, "cachedLocators"); - GraalError.guarantee(jvmciServiceLocatorCachedLocatorsField.get(null) == null, "Expect cachedLocators to be null"); - Iterable serviceLocators = ServiceLoader.load(JVMCIServiceLocator.class, LOADER); - List cachedLocators = new ArrayList<>(); - serviceLocators.forEach(cachedLocators::add); - jvmciServiceLocatorCachedLocatorsField.set(null, cachedLocators); - - EconomicMap libgraalObjects = (EconomicMap) ObjectCopier.decode(encodedGuestObjects, LOADER); - EncodedSnippets encodedSnippets = (EncodedSnippets) libgraalObjects.get("encodedSnippets"); - - // Mark all the Node classes as allocated so they are available during graph decoding. - for (NodeClass nodeClass : encodedSnippets.getSnippetNodeClasses()) { - registerAsInHeap.accept(nodeClass.getClazz()); - } - HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); - - List foreignCallSignatures = (List) libgraalObjects.get("foreignCallSignatures"); - HotSpotForeignCallLinkage.Stubs.initStubs(foreignCallSignatures); - } catch (ReflectiveOperationException e) { - throw GraalError.shouldNotReachHere(e); - } - } - - private static final Lookup MHL = MethodHandles.lookup(); - - /** - * Gets method handles to call Graal and JVMCI methods. - * - * @return a named set of handles - */ - public static Map getRuntimeHandles() { - try { - return Map.of("compileMethod", MHL.findStatic(RunTime.class, "compileMethod", - methodType(long.class, long.class, - boolean.class, boolean.class, boolean.class, boolean.class, - long.class, int.class, int.class, - String.class, BiConsumer.class, Supplier.class)), - "hashConstantOopFields", MHL.findStatic(RunTime.class, "hashConstantOopFields", - methodType(long.class, long.class, boolean.class, int.class, int.class, - boolean.class, Runnable.class)), - "getJNIEnv", MHL.findStatic(RunTime.class, "getJNIEnv", - methodType(long.class)), - "attachCurrentThread", MHL.findStatic(RunTime.class, "attachCurrentThread", - methodType(boolean.class, boolean.class, long[].class)), - "detachCurrentThread", MHL.findStatic(RunTime.class, "detachCurrentThread", - methodType(boolean.class, boolean.class)), - "getSavedProperty", MHL.findStatic(GraalServices.class, "getSavedProperty", - methodType(String.class, String.class)), - "ttyPrintf", MHL.findStatic(TTY.class, "printf", - methodType(void.class, String.class, Object[].class))); - } catch (Throwable e) { - throw GraalError.shouldNotReachHere(e); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/RunTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/RunTime.java deleted file mode 100644 index d8fa6c3419bc..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/RunTime.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal; - -import java.util.Arrays; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -import org.graalvm.collections.EconomicMap; - -import jdk.graal.compiler.debug.GlobalMetrics; -import jdk.graal.compiler.hotspot.CompilationContext; -import jdk.graal.compiler.hotspot.CompilationTask; -import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; -import jdk.graal.compiler.hotspot.HotSpotGraalRuntime; -import jdk.graal.compiler.hotspot.HotSpotGraalServices; -import jdk.graal.compiler.hotspot.ProfileReplaySupport; -import jdk.graal.compiler.options.OptionDescriptors; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.options.OptionsParser; -import jdk.graal.compiler.util.OptionsEncoder; -import jdk.internal.misc.Unsafe; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotInstalledCode; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.runtime.JVMCIBackend; -import jdk.vm.ci.runtime.JVMCICompiler; - -/** - * This class provides implementations for {@code @CEntryPoint}s that libgraal has to provide as a - * JVM JIT compiler as well as handles (created by {@link BuildTime#getRuntimeHandles}) to other - * utility methods needed by {@code LibGraalFeature}. - */ -public class RunTime { - - private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - - private record CachedOptions(OptionValues options, long hash) { - } - - private static final ThreadLocal CACHED_OPTIONS_THREAD_LOCAL = new ThreadLocal<>(); - - private static OptionValues decodeOptions(long address, int size, int hash) { - CachedOptions options = CACHED_OPTIONS_THREAD_LOCAL.get(); - if (options == null || options.hash != hash) { - byte[] buffer = new byte[size]; - UNSAFE.copyMemory(null, address, buffer, Unsafe.ARRAY_BYTE_BASE_OFFSET, size); - int actualHash = Arrays.hashCode(buffer); - if (actualHash != hash) { - throw new IllegalArgumentException(actualHash + " != " + hash); - } - Map srcMap = OptionsEncoder.decode(buffer); - final EconomicMap, Object> dstMap = OptionValues.newOptionMap(); - final Iterable loader = OptionsParser.getOptionsLoader(); - for (Map.Entry e : srcMap.entrySet()) { - final String optionName = e.getKey(); - final Object optionValue = e.getValue(); - OptionsParser.parseOption(optionName, optionValue, dstMap, loader); - } - - options = new CachedOptions(new OptionValues(dstMap), hash); - CACHED_OPTIONS_THREAD_LOCAL.set(options); - } - return options.options; - } - - /** - * This is the implementation that {@code @CEntryPoint}-method - * {@code com.oracle.svm.graal.hotspot.libgraal.LibGraalEntryPoints#compileMethod} delegates to. - * Most parameters are identical to the caller method parameters except for the following: - * - * @param profileLoadPath value of the {@code Options#LoadProfiles} option or null - * @param timeAndMemConsumer allows caller to get info about compile time and memory consumption - * @param currentThreadAllocatedBytes gives access to - * {@code com.sun.management.ThreadMXBean#getCurrentThreadAllocatedBytes()} needed to - * compute memory consumption during compilation - */ - @SuppressWarnings("try") - public static long compileMethod(long methodHandle, boolean useProfilingInfo, - boolean installAsDefault, boolean printMetrics, boolean eagerResolving, - long optionsAddress, int optionsSize, int optionsHash, - String profileLoadPath, BiConsumer timeAndMemConsumer, - Supplier currentThreadAllocatedBytes) { - - HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); - HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - if (methodHandle == 0L) { - return 0L; - } - - int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; - HotSpotResolvedJavaMethod method = runtime.unhand(HotSpotResolvedJavaMethod.class, methodHandle); - HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); - try (CompilationContext ignored = HotSpotGraalServices.openLocalCompilationContext(request)) { - CompilationTask task = new CompilationTask(runtime, compiler, request, useProfilingInfo, false, false, eagerResolving, installAsDefault); - long allocatedBytesBefore = 0; - long timeBefore = 0; - if (timeAndMemConsumer != null) { - allocatedBytesBefore = currentThreadAllocatedBytes.get(); - timeBefore = System.nanoTime(); - } - OptionValues options = decodeOptions(optionsAddress, optionsSize, optionsHash); - if (profileLoadPath != null) { - options = new OptionValues(options, ProfileReplaySupport.Options.LoadProfiles, profileLoadPath); - } - task.runCompilation(options); - if (timeAndMemConsumer != null) { - long allocatedBytesAfter = currentThreadAllocatedBytes.get(); - long bytesAllocated = allocatedBytesAfter - allocatedBytesBefore; - long timeAfter = System.nanoTime(); - long timeSpent = timeAfter - timeBefore; - timeAndMemConsumer.accept(timeSpent, bytesAllocated); - } - HotSpotInstalledCode installedCode = task.getInstalledCode(); - if (printMetrics) { - GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues(); - metricValues.print(options); - metricValues.clear(); - } - return runtime.translate(installedCode); - } - } - - @SuppressWarnings({"unused", "try"}) - public static long hashConstantOopFields(long typeHandle, boolean useScope, int iterations, - int oopsPerIteration, boolean verbose, Runnable doReferenceHandling) { - HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); - JVMCIBackend backend = runtime.getHostJVMCIBackend(); - ConstantReflectionProvider constantReflection = backend.getConstantReflection(); - HotSpotResolvedJavaType type = runtime.unhand(HotSpotResolvedJavaType.class, typeHandle); - ResolvedJavaField[] staticFields = type.getStaticFields(); - JavaConstant receiver = null; - long hash = 13; - - Object scopeDescription = "TestingOopHandles"; - - int remainingIterations = iterations; - while (remainingIterations-- > 0) { - ResolvedJavaField lastReadField = null; - try (CompilationContext scope = useScope ? HotSpotGraalServices.openLocalCompilationContext(scopeDescription) : null) { - if (verbose && useScope) { - System.out.println("Opened " + scopeDescription); - } - int remainingOops = oopsPerIteration; - while (remainingOops-- > 0) { - for (ResolvedJavaField field : staticFields) { - if (field.getType().getJavaKind() == JavaKind.Object) { - JavaConstant value = constantReflection.readFieldValue(field, receiver); - if (value != null) { - lastReadField = field; - hash = hash ^ value.hashCode(); - } - } - } - } - } - if (!useScope) { - System.gc(); - if (verbose) { - System.out.println("calling reference handling"); - } - doReferenceHandling.run(); - if (verbose) { - System.out.println("called reference handling"); - } - // Need one more remote oop creation to trigger releasing - // of remote oops that were wrapped in weakly reachable - // IndirectHotSpotObjectConstantImpl objects just collected. - constantReflection.readFieldValue(lastReadField, receiver); - } else if (verbose) { - System.out.println(" Closed " + scopeDescription); - } - } - return hash; - } - - private static long jniEnvironmentOffset = Integer.MAX_VALUE; - - private static long getJniEnvironmentOffset() { - if (jniEnvironmentOffset == Integer.MAX_VALUE) { - HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); - HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - HotSpotVMConfigAccess config = new HotSpotVMConfigAccess(store); - jniEnvironmentOffset = config.getFieldOffset("JavaThread::_jni_environment", Integer.class, "JNIEnv"); - } - return jniEnvironmentOffset; - } - - /** - * Gets the JNIEnv value for the current HotSpot thread. - */ - static long getJNIEnv() { - HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); - long offset = getJniEnvironmentOffset(); - long javaThreadAddr = jvmciRuntime.getCurrentJavaThread(); - return javaThreadAddr + offset; - } - - /** - * Ensures the current thread is attached to the peer runtime. - * - * @param isDaemon if the thread is not yet attached, should it be attached as a daemon - * @param isolate if non-null, the isolate for the current thread is returned in element 0 - * @return {@code true} if this call attached the current thread, {@code false} if the current - * thread was already attached - */ - public static boolean attachCurrentThread(boolean isDaemon, long[] isolate) { - long[] javaVMInfo = isolate != null ? new long[4] : null; - boolean res = HotSpotJVMCIRuntime.runtime().attachCurrentThread(isDaemon, javaVMInfo); - if (isolate != null) { - isolate[0] = javaVMInfo[1]; - } - return res; - } - - /** - * Detaches the current thread from the peer runtime. - * - * @param release if {@code true} and the VM supports releasing the {@code JavaVM} associated - * with libgraal runtimes and this is the last thread attached to a libgraal runtime, - * then this call destroys the associated {@code JavaVM} instance, releasing its - * resources - * @return {@code true} if the {@code JavaVM} associated with the libgraal runtime was destroyed - * as a result of this call - */ - public static boolean detachCurrentThread(boolean release) { - return HotSpotJVMCIRuntime.runtime().detachCurrentThread(release); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/BuildTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/BuildTime.java deleted file mode 100644 index 2e82e70c908a..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/BuildTime.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; -import jdk.graal.compiler.truffle.host.TruffleHostEnvironment; -import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Set; - -/** - * Class used to initialize the Truffle extensions to the Graal compiler in the image build time. - */ -@Platforms(Platform.HOSTED_ONLY.class) -public class BuildTime { - - private static Lookup hostLookup; - private static Class truffleFromLibGraalStartPoint; - private static Class nativeImageHostEntryPoint; - private static Map hostMethods; - - /** - * Configures Truffle services to the Graal compiler in the image build time. - */ - public static void configureGraalForLibGraal() { - TruffleHostEnvironment.overrideLookup(new LibGraalTruffleHostEnvironmentLookup()); - } - - /** - * Obtains a {@link Lookup} instance for resolving method handles to invoke Graal and JVMCI - * methods. - *

- * This method is invoked reflectively by {@code LibGraalFeature.initializeTruffle()} in the - * native-image classloader to facilitate the exchange of lookup instances between the - * native-image classloader and the LibGraalClassLoader. - *

- * - * @param lookup a {@link Lookup} instance used to resolve handles for calling into the - * native-image host. - * @param fromLibGraal a class that contains methods for making calls to HotSpot using the JNI - * API. - * @param nativeImageSupport a class that provides native-image and JNI helper methods. - * @return a {@link Entry} containing a {@link Lookup} instance and a class with compiler entry - * methods. The {@link Lookup} instance can be used to resolve the compiler entry - * methods within the provided class. - */ - public static Entry> initializeLookup(Lookup lookup, Class fromLibGraal, Class nativeImageSupport) { - if (hostLookup != null) { - throw new IllegalStateException("Host lookup has already been initialized. BuildTime.initializeLookup should only be called once during the native image build process."); - } - hostLookup = Objects.requireNonNull(lookup, "lookup must be non null"); - truffleFromLibGraalStartPoint = Objects.requireNonNull(fromLibGraal, "fromLibGraal must be non null"); - nativeImageHostEntryPoint = Objects.requireNonNull(nativeImageSupport, "nativeImageSupport must be non null"); - return Map.entry(MethodHandles.lookup(), GraalEntryPoints.class); - } - - static MethodHandle getHostMethodHandleOrFail(Id id) { - return getHostMethodHandleOrFail(id.getMethodName()); - } - - static MethodHandle getHostMethodHandleOrFail(String name) { - if (ImageInfo.inImageBuildtimeCode()) { - /* - * Native-image initializes BuildTime also in the platform classloader. In this case we - * return null. - */ - ClassLoader myLoader = BuildTime.class.getClassLoader(); - if (myLoader == null || myLoader == ClassLoader.getPlatformClassLoader() || myLoader == ClassLoader.getSystemClassLoader()) { - return null; - } - if (hostMethods == null) { - hostMethods = initializeHostMethods(); - } - MethodHandle handle = hostMethods.get(name); - if (handle != null) { - return handle; - } else { - throw new NoSuchElementException(name); - } - } else if (ImageInfo.inImageRuntimeCode()) { - /* - * The getHostMethodHandleOrFail should never be called in the native-image execution - * time. - */ - throw new IllegalStateException("Should not be reachable at libgraal runtime"); - } else { - /* - * HS proxy classes and BuildTime are not used in Jargraal, but the CheckGraalInvariants - * test eagerly initializes these proxy classes, leading to a call to - * getHostMethodHandleOrFail. In this scenario, we return null to prevent the test from - * crashing. - */ - return null; - } - } - - private static Map initializeHostMethods() { - try { - Map result = new HashMap<>(); - Set methodNames = new HashSet<>(); - Arrays.stream(Id.values()).map(Id::getMethodName).forEach(methodNames::add); - for (Method m : truffleFromLibGraalStartPoint.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())) { - String methodName = m.getName(); - if (methodNames.remove(methodName)) { - result.put(methodName, hostLookup.unreflect(m)); - } - } - } - if (!methodNames.isEmpty()) { - throw new RuntimeException(String.format("Cannot find methods for following ids %s in %s", methodNames, truffleFromLibGraalStartPoint.getName())); - } - Arrays.stream(NativeImageHostCalls.class.getDeclaredMethods()).map(Method::getName).forEach(methodNames::add); - for (Method m : nativeImageHostEntryPoint.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())) { - String methodName = m.getName(); - if (methodNames.remove(methodName)) { - if (result.put(methodName, hostLookup.unreflect(m)) != null) { - throw new RuntimeException(String.format("Duplicate methods for name %s in %s", methodName, nativeImageHostEntryPoint)); - } - } - } - } - if (!methodNames.isEmpty()) { - throw new RuntimeException(String.format("Cannot find following methods %s in %s", methodNames, nativeImageHostEntryPoint)); - } - return result; - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/GraalEntryPoints.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/GraalEntryPoints.java deleted file mode 100644 index 2ffb4549e130..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/GraalEntryPoints.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import java.util.function.Supplier; - -import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.TruffleCompilerListener.CompilationResultInfo; -import com.oracle.truffle.compiler.TruffleCompilerListener.GraphInfo; -import com.oracle.truffle.compiler.TruffleCompilerOptionDescriptor; - -import jdk.graal.compiler.hotspot.CompilationContext; -import jdk.graal.compiler.hotspot.HotSpotGraalServices; -import jdk.graal.compiler.truffle.TruffleCompilerOptions; -import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilationSupport; -import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Guest Graal entry points for Truffle to libgraal calls. - */ -public final class GraalEntryPoints { - - private GraalEntryPoints() { - } - - // HotSpot to libgraal entry points - - public static void initializeIsolate() { - TruffleLibGraalShutdownHook.registerShutdownHook(); - } - - public static boolean registerRuntime(long truffleRuntimeWeakRef) { - return LibGraalTruffleHostEnvironmentLookup.registerRuntime(truffleRuntimeWeakRef); - } - - public static Object initializeRuntime(Object hsHandle, long hsClassLoaderDelegate) { - return new HSTruffleCompilerRuntime(hsHandle, hsClassLoaderDelegate); - } - - public static Object newCompiler(Object truffleCompilerRuntime) { - /* - * Unlike `LibGraalTruffleHostEnvironment`, Truffle libgraal entry points use the global - * compilation context by default, so we don't need to call - * `HotSpotGraalServices.enterGlobalCompilationContext()` before creating - * `TruffleCompilerImpl`. The `doCompile` method enters a local compilation context through - * its own call to `HotSpotGraalServices.openLocalCompilationContext`. - */ - return HotSpotTruffleCompilerImpl.create((HSTruffleCompilerRuntime) truffleCompilerRuntime, null); - } - - public static void initializeCompiler(Object compiler, Object compilableHsHandle, boolean firstInitialization) { - HotSpotTruffleCompilerImpl truffleCompiler = (HotSpotTruffleCompilerImpl) compiler; - TruffleCompilable compilable = new HSTruffleCompilable(compilableHsHandle); - truffleCompiler.initialize(compilable, firstInitialization); - } - - public static String getCompilerConfigurationFactoryName() { - return HotSpotTruffleCompilationSupport.getLazyCompilerConfigurationName(); - } - - @SuppressWarnings("try") - public static void doCompile(Object compiler, Object taskHsHandle, Object compilableHsHandle, Object listenerHsHandle) { - HotSpotTruffleCompilerImpl truffleCompiler = (HotSpotTruffleCompilerImpl) compiler; - HSTruffleCompilationTask task = taskHsHandle == null ? null : new HSTruffleCompilationTask(taskHsHandle); - HSTruffleCompilerListener listener = listenerHsHandle == null ? null : new HSTruffleCompilerListener(listenerHsHandle); - HSTruffleCompilable compilable = new HSTruffleCompilable(compilableHsHandle); - try (CompilationContext hotSpotObjectConstantScope = HotSpotGraalServices.openLocalCompilationContext(compilable)) { - truffleCompiler.doCompile(task, compilable, listener); - } - } - - public static void shutdown(Object compiler) { - ((HotSpotTruffleCompilerImpl) compiler).shutdown(); - } - - public static void installTruffleCallBoundaryMethod(Object compiler, long methodHandle) { - HotSpotTruffleCompilerImpl truffleCompiler = (HotSpotTruffleCompilerImpl) compiler; - truffleCompiler.installTruffleCallBoundaryMethod(HotSpotJVMCIRuntime.runtime().unhand(ResolvedJavaMethod.class, methodHandle), null); - } - - public static void installTruffleReservedOopMethod(Object compiler, long methodHandle) { - HotSpotTruffleCompilerImpl truffleCompiler = (HotSpotTruffleCompilerImpl) compiler; - truffleCompiler.installTruffleReservedOopMethod(HotSpotJVMCIRuntime.runtime().unhand(ResolvedJavaMethod.class, methodHandle), null); - } - - public static int pendingTransferToInterpreterOffset(Object compiler, Object compilableHsHandle) { - HotSpotTruffleCompilerImpl truffleCompiler = (HotSpotTruffleCompilerImpl) compiler; - TruffleCompilable compilable = new HSTruffleCompilable(compilableHsHandle); - return truffleCompiler.pendingTransferToInterpreterOffset(compilable); - } - - @SuppressWarnings("unchecked") - public static String getSuppliedString(Object stringSupplier) { - return ((Supplier) stringSupplier).get(); - } - - public static int getNodeCount(Object graphInfo) { - return ((GraphInfo) graphInfo).getNodeCount(); - } - - public static String[] getNodeTypes(Object graphInfo, boolean simpleNames) { - return ((GraphInfo) graphInfo).getNodeTypes(simpleNames); - } - - public static long getCompilationId(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getCompilationId(); - } - - public static int getTargetCodeSize(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getTargetCodeSize(); - } - - public static int getTotalFrameSize(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getTotalFrameSize(); - } - - public static int getExceptionHandlersCount(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getExceptionHandlersCount(); - } - - public static int getInfopointsCount(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getInfopointsCount(); - } - - public static String[] getInfopoints(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getInfopoints(); - } - - public static int getMarksCount(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getMarksCount(); - } - - public static int getDataPatchesCount(Object compilationResultInfo) { - return ((CompilationResultInfo) compilationResultInfo).getDataPatchesCount(); - } - - public static Object[] listCompilerOptions() { - TruffleCompilerOptionDescriptor[] options = TruffleCompilerOptions.listOptions(); - Object[] result = new Object[options.length]; - for (int i = 0; i < options.length; i++) { - TruffleCompilerOptionDescriptor option = options[i]; - result[i] = NativeImageHostCalls.createTruffleCompilerOptionDescriptor(option.name(), option.type().ordinal(), option.deprecated(), option.help(), option.deprecationMessage()); - } - return result; - } - - public static boolean compilerOptionExists(String optionName) { - return TruffleCompilerOptions.optionExists(optionName); - } - - public static String validateCompilerOption(String optionName, String optionValue) { - return TruffleCompilerOptions.validateOption(optionName, optionValue); - } - - public static void purgePartialEvaluationCaches(Object compiler) { - ((HotSpotTruffleCompilerImpl) compiler).purgePartialEvaluationCaches(); - } - - public static String getCompilerVersion() { - return HSTruffleCompilerRuntime.COMPILER_VERSION; - } - - public static long getCurrentJavaThread() { - return HotSpotJVMCIRuntime.runtime().getCurrentJavaThread(); - } - - public static int getLastJavaPCOffset() { - HotSpotVMConfigAccess configAccess = new HotSpotVMConfigAccess(HotSpotJVMCIRuntime.runtime().getConfigStore()); - int anchor = configAccess.getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor"); - int lastJavaPc = configAccess.getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address"); - return anchor + lastJavaPc; - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSIndirectHandle.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSIndirectHandle.java deleted file mode 100644 index 184a9e396ac5..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSIndirectHandle.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import java.util.Objects; - -/** - * Base class for HS proxy classes loaded by {@code LibGraalClassLoader} that use - * {@link java.lang.invoke.MethodHandle}s to perform JNI calls in a native-image host. - * - *

- * Implementation: This class maintains a strong reference to an {@code HSObject} instance created - * in the native-image host. For global or weak-global JNI references, the {@code HSObject} - * registers a cleaner to manage the deletion of the JNI reference. When the - * {@link HSIndirectHandle} instance becomes weakly reachable, the corresponding {@code HSObject} - * instance in the native-image host also becomes weakly reachable. The registered cleaner then - * deletes the associated JNI global or weak-global reference. - *

- */ -class HSIndirectHandle { - - /** - * The {@code HSObject} instance created in the native-image host. - */ - final Object hsHandle; - - /** - * Constructs an {@code HSIndirectHandle} with a non-null {@code HSObject} reference. - * - * @param hsHandle the reference to {@code HSObject} allocated in the native-image host, must - * not be null. - * @throws NullPointerException if {@code hsHandle} is null. - */ - HSIndirectHandle(Object hsHandle) { - this.hsHandle = Objects.requireNonNull(hsHandle, "HsHandle must be non-null"); - } - - /** - * Handles exceptions by rethrowing them as either {@link RuntimeException} or {@link Error}, or - * wrapping them in a {@link RuntimeException} if they are of another type. - */ - static RuntimeException handleException(Throwable t) { - if (t instanceof RuntimeException rt) { - throw rt; - } else if (t instanceof Error e) { - throw e; - } else { - throw new RuntimeException(t); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilable.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilable.java deleted file mode 100644 index c9923862d9da..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilable.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -import java.lang.invoke.MethodHandle; -import java.util.Map; -import java.util.function.Supplier; - -import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; - -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.HotSpotGraalServices; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.SpeculationLog; - -final class HSTruffleCompilable extends HSIndirectHandle implements TruffleCompilable { - - private static final Handles HANDLES = new Handles(); - - /** - * Handle to {@code speculationLog} field of the {@code OptimizedCallTarget}. - */ - private Long cachedFailedSpeculationsAddress; - private volatile String cachedName; - private volatile String cachedString; - - HSTruffleCompilable(Object hsHandle) { - super(hsHandle); - } - - @Override - public SpeculationLog getCompilationSpeculationLog() { - Long res = cachedFailedSpeculationsAddress; - if (res == null) { - try { - res = (long) HANDLES.getFailedSpeculationsAddress.invoke(hsHandle); - cachedFailedSpeculationsAddress = res; - } catch (Throwable t) { - throw handleException(t); - } - } - return HotSpotGraalServices.newHotSpotSpeculationLog(cachedFailedSpeculationsAddress); - } - - @Override - @SuppressWarnings("unchecked") - public Map getCompilerOptions() { - try { - return (Map) HANDLES.getCompilerOptions.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public long engineId() { - try { - return (long) HANDLES.engineId.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean prepareForCompilation(boolean rootCompilation, int compilationTier, boolean lastTier) { - try { - return (boolean) HANDLES.prepareForCompilation.invoke(hsHandle, rootCompilation, compilationTier, lastTier); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean isTrivial() { - try { - return (boolean) HANDLES.isTrivial.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public JavaConstant asJavaConstant() { - long constantHandle; - try { - constantHandle = (long) HANDLES.asJavaConstant.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - return HotSpotJVMCIRuntime.runtime().unhand(JavaConstant.class, constantHandle); - } - - @Override - public void onCompilationFailed(Supplier serializedException, boolean suppressed, boolean bailout, boolean permanentBailout, boolean graphTooBig) { - try { - Object serializedExceptionHsHandle = HANDLES.createStringSupplier.invoke(serializedException); - HANDLES.onCompilationFailed.invoke(hsHandle, serializedExceptionHsHandle, suppressed, bailout, permanentBailout, graphTooBig); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void onCompilationSuccess(int compilationTier, boolean lastTier) { - NativeImageHostCalls.onCompilationSuccess(hsHandle, compilationTier, lastTier); - } - - @Override - public boolean onInvalidate(Object source, CharSequence reason, boolean wasActive) { - throw GraalError.shouldNotReachHere("Should not be reachable."); // ExcludeFromJacocoGeneratedReport - } - - @Override - public String getName() { - String res = cachedName; - if (res == null) { - try { - res = (String) HANDLES.getCompilableName.invoke(hsHandle); - cachedName = res; - } catch (Throwable t) { - throw handleException(t); - } - } - return res; - } - - @Override - public String toString() { - String res = cachedString; - if (res == null) { - try { - res = (String) HANDLES.compilableToString.invoke(hsHandle); - cachedString = res; - } catch (Throwable t) { - throw handleException(t); - } - } - return res; - } - - @Override - public int getNonTrivialNodeCount() { - try { - return (int) HANDLES.getNonTrivialNodeCount.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int countDirectCallNodes() { - try { - return (int) HANDLES.countDirectCallNodes.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getCallCount() { - try { - return (int) HANDLES.getCompilableCallCount.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean cancelCompilation(CharSequence reason) { - try { - return (boolean) HANDLES.cancelCompilation.invoke(hsHandle, reason); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean isSameOrSplit(TruffleCompilable ast) { - try { - return (boolean) HANDLES.isSameOrSplit.invoke(hsHandle, ast == null ? null : ((HSTruffleCompilable) ast).hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getKnownCallSiteCount() { - try { - return (int) HANDLES.getKnownCallSiteCount.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - private static final class Handles { - final MethodHandle getFailedSpeculationsAddress = getHostMethodHandleOrFail(Id.GetFailedSpeculationsAddress); - final MethodHandle getCompilerOptions = getHostMethodHandleOrFail(Id.GetCompilerOptions); - final MethodHandle engineId = getHostMethodHandleOrFail(Id.EngineId); - final MethodHandle prepareForCompilation = getHostMethodHandleOrFail(Id.PrepareForCompilation); - final MethodHandle isTrivial = getHostMethodHandleOrFail(Id.IsTrivial); - final MethodHandle asJavaConstant = getHostMethodHandleOrFail(Id.AsJavaConstant); - final MethodHandle getCompilableName = getHostMethodHandleOrFail(Id.GetCompilableName); - final MethodHandle createStringSupplier = getHostMethodHandleOrFail(Id.CreateStringSupplier); - final MethodHandle onCompilationFailed = getHostMethodHandleOrFail(Id.OnCompilationFailed); - final MethodHandle getNonTrivialNodeCount = getHostMethodHandleOrFail(Id.GetNonTrivialNodeCount); - final MethodHandle countDirectCallNodes = getHostMethodHandleOrFail(Id.CountDirectCallNodes); - final MethodHandle getCompilableCallCount = getHostMethodHandleOrFail(Id.GetCompilableCallCount); - final MethodHandle compilableToString = getHostMethodHandleOrFail(Id.CompilableToString); - final MethodHandle cancelCompilation = getHostMethodHandleOrFail(Id.CancelCompilation); - final MethodHandle isSameOrSplit = getHostMethodHandleOrFail(Id.IsSameOrSplit); - final MethodHandle getKnownCallSiteCount = getHostMethodHandleOrFail(Id.GetKnownCallSiteCount); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilationTask.java deleted file mode 100644 index ef2fae863c73..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilationTask.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.TruffleCompilationTask; -import com.oracle.truffle.compiler.TruffleSourceLanguagePosition; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.meta.JavaConstant; - -import java.lang.invoke.MethodHandle; -import java.util.Map; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -final class HSTruffleCompilationTask extends HSIndirectHandle implements TruffleCompilationTask { - - private static final Handles HANDLES = new Handles(); - - HSTruffleCompilationTask(Object hsHandle) { - super(hsHandle); - } - - @Override - public boolean isCancelled() { - try { - return (boolean) HANDLES.isCancelled.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean isLastTier() { - try { - return (boolean) HANDLES.isLastTier.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public boolean hasNextTier() { - try { - return (boolean) HANDLES.hasNextTier.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public TruffleSourceLanguagePosition getPosition(JavaConstant node) { - long nodeHandle = HotSpotJVMCIRuntime.runtime().translate(node); - Object positionHsHandle; - try { - positionHsHandle = HANDLES.getPosition.invoke(hsHandle, nodeHandle); - } catch (Throwable t) { - throw handleException(t); - } - if (positionHsHandle == null) { - return null; - } else { - return new HSTruffleSourceLanguagePosition(positionHsHandle); - } - } - - @Override - public void addTargetToDequeue(TruffleCompilable target) { - try { - HANDLES.addTargetToDequeue.invoke(hsHandle, ((HSTruffleCompilable) target).hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void setCallCounts(int total, int inlined) { - try { - HANDLES.setCallCounts.invoke(hsHandle, total, inlined); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void addInlinedTarget(TruffleCompilable target) { - try { - HANDLES.addInlinedTarget.invoke(hsHandle, ((HSTruffleCompilable) target).hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - @SuppressWarnings("unchecked") - public Map getDebugProperties(JavaConstant node) { - try { - long nodeHandle = HotSpotJVMCIRuntime.runtime().translate(node); - return (Map) HANDLES.getDebugProperties.invoke(hsHandle, nodeHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - private static final class Handles { - final MethodHandle isCancelled = getHostMethodHandleOrFail(Id.IsCancelled); - final MethodHandle hasNextTier = getHostMethodHandleOrFail(Id.HasNextTier); - final MethodHandle isLastTier = getHostMethodHandleOrFail(Id.IsLastTier); - final MethodHandle getPosition = getHostMethodHandleOrFail(Id.GetPosition); - final MethodHandle addTargetToDequeue = getHostMethodHandleOrFail(Id.AddTargetToDequeue); - final MethodHandle setCallCounts = getHostMethodHandleOrFail(Id.SetCallCounts); - final MethodHandle addInlinedTarget = getHostMethodHandleOrFail(Id.AddInlinedTarget); - final MethodHandle getDebugProperties = getHostMethodHandleOrFail(Id.GetDebugProperties); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerListener.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerListener.java deleted file mode 100644 index 8741ddac9cde..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerListener.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.TruffleCompilationTask; -import com.oracle.truffle.compiler.TruffleCompilerListener; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; - -import java.lang.invoke.MethodHandle; -import java.util.function.Supplier; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -final class HSTruffleCompilerListener extends HSIndirectHandle implements TruffleCompilerListener { - - private static final Handles HANDLES = new Handles(); - - HSTruffleCompilerListener(Object hsHandle) { - super(hsHandle); - } - - @Override - public void onSuccess(TruffleCompilable compilable, TruffleCompilationTask task, GraphInfo graphInfo, CompilationResultInfo compilationResultInfo, int tier) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - Object hsTask = ((HSTruffleCompilationTask) task).hsHandle; - try { - HANDLES.onSuccess.invoke(hsHandle, hsCompilable, hsTask, graphInfo, compilationResultInfo, tier); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void onTruffleTierFinished(TruffleCompilable compilable, TruffleCompilationTask task, GraphInfo graph) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - Object hsTask = ((HSTruffleCompilationTask) task).hsHandle; - try { - HANDLES.onTruffleTierFinished.invoke(hsHandle, hsCompilable, hsTask, graph); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void onGraalTierFinished(TruffleCompilable compilable, GraphInfo graph) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - try { - HANDLES.onGraalTierFinished.invoke(hsHandle, hsCompilable, graph); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void onFailure(TruffleCompilable compilable, String reason, boolean bailout, boolean permanentBailout, int tier, Supplier lazyStackTrace) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - try { - HANDLES.onFailure.invoke(hsHandle, hsCompilable, reason, bailout, permanentBailout, tier, lazyStackTrace); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public void onCompilationRetry(TruffleCompilable compilable, TruffleCompilationTask task) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - Object hsTask = ((HSTruffleCompilationTask) task).hsHandle; - try { - HANDLES.onCompilationRetry.invoke(hsHandle, hsCompilable, hsTask); - } catch (Throwable t) { - throw handleException(t); - } - } - - private static final class Handles { - final MethodHandle onSuccess = getHostMethodHandleOrFail(Id.OnSuccess); - final MethodHandle onTruffleTierFinished = getHostMethodHandleOrFail(Id.OnTruffleTierFinished); - final MethodHandle onGraalTierFinished = getHostMethodHandleOrFail(Id.OnGraalTierFinished); - final MethodHandle onFailure = getHostMethodHandleOrFail(Id.OnFailure); - final MethodHandle onCompilationRetry = getHostMethodHandleOrFail(Id.OnCompilationRetry); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleSourceLanguagePosition.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleSourceLanguagePosition.java deleted file mode 100644 index 0895789ec68c..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleSourceLanguagePosition.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import com.oracle.truffle.compiler.TruffleSourceLanguagePosition; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; - -import java.lang.invoke.MethodHandle; -import java.net.URI; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -final class HSTruffleSourceLanguagePosition extends HSIndirectHandle implements TruffleSourceLanguagePosition { - - private static final Handles HANDLES = new Handles(); - - HSTruffleSourceLanguagePosition(Object hsHandle) { - super(hsHandle); - } - - @Override - public String getDescription() { - try { - return (String) HANDLES.getDescription.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getOffsetEnd() { - try { - return (int) HANDLES.getOffsetEnd.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getOffsetStart() { - try { - return (int) HANDLES.getOffsetStart.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getLineNumber() { - try { - return (int) HANDLES.getLineNumber.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public URI getURI() { - String uri; - try { - uri = (String) HANDLES.getURI.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - return uri == null ? null : URI.create(uri); - } - - @Override - public String getLanguage() { - try { - return (String) HANDLES.getLanguage.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public int getNodeId() { - try { - return (int) HANDLES.getNodeId.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - @Override - public String getNodeClassName() { - try { - return (String) HANDLES.getNodeClassName.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } - } - - private static final class Handles { - final MethodHandle getOffsetStart = getHostMethodHandleOrFail(Id.GetOffsetStart); - final MethodHandle getOffsetEnd = getHostMethodHandleOrFail(Id.GetOffsetEnd); - final MethodHandle getLineNumber = getHostMethodHandleOrFail(Id.GetLineNumber); - final MethodHandle getLanguage = getHostMethodHandleOrFail(Id.GetLanguage); - final MethodHandle getDescription = getHostMethodHandleOrFail(Id.GetDescription); - final MethodHandle getURI = getHostMethodHandleOrFail(Id.GetURI); - final MethodHandle getNodeClassName = getHostMethodHandleOrFail(Id.GetNodeClassName); - final MethodHandle getNodeId = getHostMethodHandleOrFail(Id.GetNodeId); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/NativeImageHostCalls.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/NativeImageHostCalls.java deleted file mode 100644 index 0b3183f57d77..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/NativeImageHostCalls.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -import java.lang.invoke.MethodHandle; - -/** - * Methods to call Native image specific API. - */ -final class NativeImageHostCalls { - - private static final Handles HANDLES = new Handles(); - - private NativeImageHostCalls() { - } - - // libgraal to native-image upcalls - - static void initializeHost(long runtimeClass) { - try { - HANDLES.initializeHost.invoke(runtimeClass); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static Object createLocalHandleForLocalReference(long jniLocalHandle) { - try { - return HANDLES.createLocalHandleForLocalReference.invoke(jniLocalHandle); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static Object createLocalHandleForWeakGlobalReference(long jniLocalHandle) { - try { - return HANDLES.createLocalHandleForWeakGlobalReference.invoke(jniLocalHandle); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static Object createGlobalHandle(Object hsHandle, boolean allowGlobalDuplicates) { - try { - return HANDLES.createGlobalHandle.invoke(hsHandle, allowGlobalDuplicates); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static boolean isSameObject(Object o1, Object o2) { - try { - return (boolean) HANDLES.isSameObject.invoke(o1, o2); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static long getObjectClass(Object o) { - try { - return (long) HANDLES.getObjectClass.invoke(o); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static Object createTruffleCompilerOptionDescriptor(String name, int type, boolean deprecated, String help, String deprecationMessage) { - try { - return HANDLES.createTruffleCompilerOptionDescriptor.invoke(name, type, deprecated, help, deprecationMessage); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - static void onCompilationSuccess(Object hsHandle, int compilationTier, boolean lastTier) { - try { - HANDLES.onCompilationSuccess.invoke(hsHandle, compilationTier, lastTier); - } catch (Throwable t) { - throw HSIndirectHandle.handleException(t); - } - } - - private static final class Handles { - final MethodHandle initializeHost = getHostMethodHandleOrFail("initializeHost"); - final MethodHandle createLocalHandleForLocalReference = getHostMethodHandleOrFail("createLocalHandleForLocalReference"); - final MethodHandle createLocalHandleForWeakGlobalReference = getHostMethodHandleOrFail("createLocalHandleForWeakGlobalReference"); - final MethodHandle createGlobalHandle = getHostMethodHandleOrFail("createGlobalHandle"); - final MethodHandle isSameObject = getHostMethodHandleOrFail("isSameObject"); - final MethodHandle getObjectClass = getHostMethodHandleOrFail("getObjectClass"); - final MethodHandle createTruffleCompilerOptionDescriptor = getHostMethodHandleOrFail("createTruffleCompilerOptionDescriptor"); - final MethodHandle onCompilationSuccess = getHostMethodHandleOrFail("onCompilationSuccess"); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/TruffleLibGraalShutdownHook.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/TruffleLibGraalShutdownHook.java deleted file mode 100644 index 8f7c013202fc..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/TruffleLibGraalShutdownHook.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.libgraal.truffle; - -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; -import jdk.graal.compiler.serviceprovider.IsolateUtil; -import jdk.graal.compiler.serviceprovider.ServiceProvider; -import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import jdk.vm.ci.services.JVMCIServiceLocator; - -import java.lang.invoke.MethodHandle; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; - -@ServiceProvider(JVMCIServiceLocator.class) -public class TruffleLibGraalShutdownHook extends JVMCIServiceLocator { - - private static volatile ShutdownHook registeredHook; - - @Override - protected S getProvider(Class service) { - ShutdownHook hook = registeredHook; - if (hook != null && service == HotSpotVMEventListener.class) { - return service.cast(hook); - } - return null; - } - - static void registerShutdownHook() { - registeredHook = new ShutdownHook(); - } - - static class ShutdownHook implements HotSpotVMEventListener { - - private static final Handles HANDLES = new Handles(); - - ShutdownHook() { - } - - @Override - public void notifyShutdown() { - try { - HANDLES.onIsolateShutdown.invoke(IsolateUtil.getIsolateID()); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - } - - private static final class Handles { - final MethodHandle onIsolateShutdown = getHostMethodHandleOrFail(Id.OnIsolateShutdown); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java index 38a8ba58551b..980a8e575877 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java @@ -50,7 +50,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.replacements.GraphKit; import jdk.graal.compiler.replacements.nodes.ReadRegisterNode; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotSignature; import jdk.vm.ci.meta.JavaMethod; @@ -59,6 +58,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; +import org.graalvm.nativeimage.ImageInfo; /** * A {@linkplain #getGraph generated} stub for a {@link Transition non-leaf} foreign call from @@ -276,7 +276,7 @@ private ResolvedJavaMethod getGraphMethod() { if (thisMethod == null) { throw new InternalError("Can't find " + getClass().getSimpleName() + ".getGraph"); } - if (GraalServices.isBuildingLibgraal()) { + if (ImageInfo.inImageBuildtimeCode()) { HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); replacements.findSnippetMethod(thisMethod); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java index ea38d909d002..9f4b69fa043f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java @@ -79,6 +79,8 @@ import jdk.vm.ci.meta.DefaultProfilingInfo; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.TriState; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; //JaCoCo Exclude @@ -158,12 +160,25 @@ public RegisterConfig getRegisterConfig() { } /** - * Gets the graph that from which the code for this stub will be compiled. + * Gets the graph from which the code for this stub will be compiled. * * @param compilationId unique compilation id for the stub */ protected abstract StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId); + /** + * Calls {@link #getGraph} for the side effect of registering the types used in the graph with + * SymbolicSnippetEncoder.snippetTypes. + */ + @Platforms(Platform.HOSTED_ONLY.class) + public final void findTypesInGraph() { + try (DebugContext debug = DebugContext.disabled(options)) { + Stub stub = linkage.getStub(); + CompilationIdentifier compilationId = new StubCompilationIdentifier(stub); + stub.getGraph(debug, compilationId); + } + } + @Override public String toString() { return "Stub<" + linkage.getDescriptor().getSignature() + ">"; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java index bdca025d0b15..c06c4e692fda 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java @@ -2411,7 +2411,7 @@ boolean checkNodeConsistency(boolean pluginResult) { @Override public void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) { - assert replacementFunction != null; + GraalError.guarantee(replacementFunction != null, "%s", targetMethod); JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass()); StampPair returnStamp = getReplacements().getGraphBuilderPlugins().getOverridingStamp(this, returnType, false); if (returnStamp == null) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/phases/LIRPhaseSuite.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/phases/LIRPhaseSuite.java index 83c1d2c1d5da..ddd7220aeecd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/phases/LIRPhaseSuite.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/phases/LIRPhaseSuite.java @@ -29,12 +29,12 @@ import java.util.List; import java.util.ListIterator; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.util.PhasePlan; import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.TimerKey; import jdk.graal.compiler.lir.gen.LIRGenerationResult; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.TargetDescription; public class LIRPhaseSuite extends LIRPhase implements PhasePlan> { @@ -105,10 +105,17 @@ public static boolean findNextPhase(ListIterator> it, Class phase : phases) { - // Notify the runtime that most objects allocated in previous LIR phase are dead and can - // be reclaimed. This will lower the chance of allocation failure in the next LIR phase. - try (DebugCloseable timer = LIRHintedGC.start(lirGenRes.getLIR().getDebug())) { - GraalServices.notifyLowMemoryPoint(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + /* + * Notify libgraal runtime that most objects allocated in previous LIR phase are + * dead and can be reclaimed. This will lower the chance of allocation failure in + * the next LIR phase. + */ + try (DebugCloseable timer = LIRHintedGC.start(lirGenRes.getLIR().getDebug())) { + libgraal.notifyLowMemoryPoint(false); + libgraal.processReferences(); + } } phase.apply(target, lirGenRes, context); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java index 21f7eff4ea06..a1cb9eaa91b6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java @@ -32,6 +32,7 @@ import java.lang.reflect.Type; import jdk.graal.compiler.api.replacements.Fold; +import jdk.graal.compiler.api.replacements.Fold.InjectedParameter; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.Node.NodeIntrinsic; import jdk.graal.compiler.nodes.ValueNode; @@ -71,6 +72,12 @@ public String getSourceLocation() { throw new GraalError("could not find method named \"execute\" in " + c.getName()); } + /** + * Determines if the {@linkplain InjectedParameter} value in {@code arg} allows folding of a + * call to {@code foldAnnotatedMethod} in the compilation context represented by {@code b}. + * + * @return true if the folding being attempted by the caller can proceed + */ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, ResolvedJavaMethod foldAnnotatedMethod) { if (inImageRuntimeCode()) { // In native image runtime compilation, there is no later stage where execution of the diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java index 5ded5f9bcc23..6d65a1d083a4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -66,7 +66,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; import jdk.graal.compiler.serviceprovider.IsolateUtil; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -977,13 +976,13 @@ public String toString() { /** * The id of the single isolate to emit output for {@link Options#PrintIntrinsics}. */ - private static final GlobalAtomicLong PRINTING_ISOLATE = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong PRINTING_ISOLATE = new GlobalAtomicLong("PRINTING_ISOLATE", 0L); /** * The intrinsic methods (in {@link Options#DisableIntrinsics} format) that have been printed by * {@link #maybePrintIntrinsics}. */ - @NativeImageReinitialize private static Set PrintedIntrinsics = new HashSet<>(); + private static Set PrintedIntrinsics = new HashSet<>(); /** * Determines if {@code plugin} is disabled by {@link Options#DisableIntrinsics}. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java index a312f77d3852..d6d86e3bdb86 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java @@ -149,10 +149,6 @@ private boolean initNames(ResolvedJavaMethod method, int parameterCount) { return true; } - public void clearNames() { - names = null; - } - public static BitSet getNonNullParameters(SnippetParameterInfo info) { BitSet nonNullParameters = new BitSet(info.getParameterCount()); for (int i = 0; i < info.getParameterCount(); i++) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionValues.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionValues.java index 19a5b7efa424..bec6a4150c97 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionValues.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionValues.java @@ -204,43 +204,42 @@ public void printHelp(Iterable loader, PrintStream out, Strin assert existing == null || existing == desc : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); } } - int size = 0; - if (all) { - size = sortedOptions.entrySet().size(); - } else { - for (Map.Entry e : sortedOptions.entrySet()) { - OptionDescriptor desc = e.getValue(); - if (!excludeOptionFromHelp(desc)) { - size++; - } - } - } - int i = 0; for (Map.Entry e : sortedOptions.entrySet()) { String key = e.getKey(); OptionDescriptor desc = e.getValue(); if (all || !excludeOptionFromHelp(desc)) { - printHelp(out, namePrefix, key, desc); - if (i++ != size - 1) { - // print new line between options - out.printf("%n"); - } + String edition = String.format("[%s edition]", OptionsParser.isEnterpriseOption(desc) ? "enterprise" : "community"); + printHelp(out, namePrefix, + key, + desc.getOptionKey().getValue(this), + desc.getOptionValueType(), + containsKey(desc.getOptionKey()) ? ":=" : "=", + edition, + desc.getHelp(), + desc.getExtraHelp()); } } } - private void printHelp(PrintStream out, String namePrefix, String key, OptionDescriptor desc) { - Object value = desc.getOptionKey().getValue(this); - if (value instanceof String) { - value = '"' + String.valueOf(value) + '"'; + private static Object quoteNonNullString(Class valueType, Object value) { + if (valueType == String.class && value != null) { + return '"' + String.valueOf(value) + '"'; } - String name = namePrefix + key; - String assign = containsKey(desc.getOptionKey()) ? ":=" : "="; - String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getOptionValueType().getSimpleName(); + return value; + } - String edition = String.format("[%s edition]", OptionsParser.isEnterpriseOption(desc) ? "enterprise" : "community"); - String linePrefix = String.format("%s %s %s %s", name, assign, value, edition); + public static void printHelp(PrintStream out, String namePrefix, + String key, + Object value, + Class valueType, + String assign, + String edition, + String help, + List extraHelp) { + String name = namePrefix + key; + String linePrefix = String.format("%s %s %s %s", name, assign, quoteNonNullString(valueType, value), edition); + String typeName = valueType.isEnum() ? "String" : valueType.getSimpleName(); int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length(); int linePad = typeStartPos - linePrefix.length(); if (linePad > 0) { @@ -250,16 +249,17 @@ private void printHelp(PrintStream out, String namePrefix, String key, OptionDes } List helpLines; - String help = desc.getHelp(); - if (help.length() != 0) { + if (!help.isEmpty()) { helpLines = wrap(help, PROPERTY_LINE_WIDTH - PROPERTY_HELP_INDENT); - helpLines.addAll(desc.getExtraHelp()); + helpLines.addAll(extraHelp); } else { - helpLines = desc.getExtraHelp(); + helpLines = extraHelp; } for (String line : helpLines) { out.printf("%" + PROPERTY_HELP_INDENT + "s%s%n", "", line); } + // print new line after each option + out.printf("%n"); } private static boolean excludeOptionFromHelp(OptionDescriptor desc) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java index cd8d3fde8ff2..2bbd56942f23 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java @@ -24,7 +24,6 @@ */ package jdk.graal.compiler.options; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.util.ArrayList; @@ -39,12 +38,11 @@ import java.util.function.Function; import java.util.regex.Pattern; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; -import jdk.graal.compiler.debug.GraalError; - /** * This class contains methods for parsing Graal options and matching them against a set of * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded via a {@link ServiceLoader}. @@ -55,9 +53,7 @@ public class OptionsParser { * Info about libgraal options. * * @param descriptors set of compiler options available in libgraal. These correspond to the - * reachable {@link OptionKey}s discovered during Native Image static analysis. This - * field is only non-null when {@link OptionsParser} is loaded by the - * LibGraalClassLoader. + * reachable {@link OptionKey}s discovered during Native Image static analysis. * @param enterpriseOptions {@linkplain OptionKey#getName() names} of enterprise options */ public record LibGraalOptionsInfo(EconomicMap descriptors, Set enterpriseOptions) { @@ -67,10 +63,9 @@ public static LibGraalOptionsInfo create() { } /** - * Compiler options info available in libgraal. This field is only non-null when - * {@link OptionsParser} is loaded by the LibGraalClassLoader. + * Compiler options info available in libgraal. */ - private static LibGraalOptionsInfo libgraalOptions; + public static final LibGraalOptionsInfo libgraalOptions = LibGraalSupport.inLibGraal() ? LibGraalOptionsInfo.create() : null; /** * Gets an iterable of available {@link OptionDescriptors}. @@ -80,11 +75,10 @@ public static Iterable getOptionsLoader() { if (inImageRuntimeCode()) { return List.of(new OptionDescriptorsMap(Objects.requireNonNull(libgraalOptions.descriptors, "missing options"))); } - boolean inLibGraal = libgraalOptions != null; - if (inLibGraal && inImageBuildtimeCode()) { + if (LibGraalSupport.inLibGraal()) { /* - * Graal code is being run in the context of the LibGraalClassLoader while building - * libgraal so use the LibGraalClassLoader to load the OptionDescriptors. + * Executing in the context of the libgraal class loader so use it to load the + * OptionDescriptors. */ ClassLoader myCL = OptionsParser.class.getClassLoader(); return ServiceLoader.load(OptionDescriptors.class, myCL); @@ -99,14 +93,6 @@ public static Iterable getOptionsLoader() { } } - @ExcludeFromJacocoGeneratedReport("only called when building libgraal") - public static LibGraalOptionsInfo setLibgraalOptions(LibGraalOptionsInfo info) { - GraalError.guarantee(inImageBuildtimeCode(), "Can only set libgraal compiler options when building libgraal"); - GraalError.guarantee(libgraalOptions == null, "Libgraal compiler options must be set exactly once"); - OptionsParser.libgraalOptions = info; - return info; - } - /** * Parses a map representing assignments of values to options. * @@ -373,6 +359,9 @@ public static boolean collectFuzzyMatches(Iterable toSearch, String name, static boolean isEnterpriseOption(OptionDescriptor desc) { if (inImageRuntimeCode()) { + if (libgraalOptions == null) { + return false; + } return Objects.requireNonNull(libgraalOptions.enterpriseOptions, "missing options").contains(desc.getName()); } Class declaringClass = desc.getDeclaringClass(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/IntrinsicMethodNodeInterface.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/IntrinsicMethodNodeInterface.java index a756d9877d77..6366ed5623c6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/IntrinsicMethodNodeInterface.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/IntrinsicMethodNodeInterface.java @@ -34,7 +34,6 @@ import jdk.graal.compiler.nodes.spi.LIRLowerable; import jdk.graal.compiler.nodes.spi.NodeLIRBuilderTool; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.Value; @@ -69,13 +68,6 @@ default void generate(NodeLIRBuilderTool gen) { } } - if (GraalServices.isBuildingLibgraal() && !canBeEmitted(gen.getLIRGeneratorTool().target().arch)) { - // When building libgraal, we unconditionally compile all stubs, including those not - // supported. In such case, we will emit hlt instruction and let the invocation plugin - // ensure the stub is not reachable. - gen.getLIRGeneratorTool().emitHalt(); - return; - } emitIntrinsic(gen); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java index c323d818c3d0..695056dae29e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java @@ -26,8 +26,14 @@ import java.lang.ref.Cleaner; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.GraalError; import jdk.internal.misc.Unsafe; +import org.graalvm.nativeimage.ImageInfo; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * A shareable long value in the JVM process that is updated atomically. The long value is stored in @@ -42,15 +48,27 @@ public class GlobalAtomicLong { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); /** - * Cleaner for freeing {@link #address}. + * Cleaner for freeing {@link #address} when executing in jargraal. */ + @Platforms(Platform.HOSTED_ONLY.class) // private static Cleaner cleaner; + /** + * Name of the global. This is only used for {@link #toString()} and is not guaranteed to be + * unique. + */ + private final String name; + /** * Address of native memory storing the long value. */ private volatile long address; + /** + * Supplies the address of the global memory storing the global value. + */ + private final Supplier addressSupplier; + /** * Value to which the value will be initialized. */ @@ -61,8 +79,33 @@ public class GlobalAtomicLong { * * @param initialValue initial value to which the long is set when its memory is allocated */ - public GlobalAtomicLong(long initialValue) { + public GlobalAtomicLong(String name, long initialValue) { + this.name = name; this.initialValue = initialValue; + if (ImageInfo.inImageRuntimeCode()) { + throw GraalError.shouldNotReachHere("Cannot create " + getClass().getName() + " objects in native image runtime"); + } else { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + if (ImageInfo.inImageRuntimeCode()) { + throw GraalError.shouldNotReachHere("The addressSupplier field value should have been replaced at image build time"); + } + addressSupplier = libgraal.createGlobal(initialValue); + } else { + // Executing in jargraal + addressSupplier = () -> { + long addr = UNSAFE.allocateMemory(Long.BYTES); + synchronized (GlobalAtomicLong.class) { + if (cleaner == null) { + cleaner = Cleaner.create(); + } + cleaner.register(GlobalAtomicLong.this, () -> UNSAFE.freeMemory(addr)); + } + UNSAFE.putLongVolatile(null, addr, initialValue); + return addr; + }; + } + } } public long getInitialValue() { @@ -71,28 +114,18 @@ public long getInitialValue() { @Override public String toString() { - long addr = getAddress(); - if (addr == 0L) { - return String.valueOf(initialValue); + if (address == 0L) { + return name + ":" + initialValue; } else { - return String.format("%d (@0x%x)", get(), addr); + return String.format("%s:%d(@0x%x)", name, get(), address); } } - // Substituted by Target_jdk_graal_compiler_serviceprovider_GlobalAtomicLong private long getAddress() { if (address == 0L) { synchronized (this) { if (address == 0L) { - long addr = UNSAFE.allocateMemory(Long.BYTES); - synchronized (GlobalAtomicLong.class) { - if (cleaner == null) { - cleaner = Cleaner.create(); - } - cleaner.register(this, () -> UNSAFE.freeMemory(addr)); - } - UNSAFE.putLongVolatile(null, addr, initialValue); - address = addr; + address = addressSupplier.get(); } } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java index 1465a850b4be..e536e6b6c7e4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java @@ -30,23 +30,28 @@ import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; +import jdk.graal.compiler.core.ArchitectureSpecific; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.vm.ci.code.Architecture; import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; import jdk.internal.misc.VM; import jdk.vm.ci.meta.EncodedSpeculationReason; import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.services.Services; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; /** * Interface to functionality that abstracts over which JDK version Graal is running on. @@ -54,34 +59,69 @@ public final class GraalServices { /** - * Returns true if code is executing in the context of building libgraal. Note that this is more - * specific than {@link ImageInfo#inImageBuildtimeCode()}. The latter will return true when - * building any native image, not just libgraal. + * Returns true if current runtime is in libgraal. Note that this is more specific than + * {@link ImageInfo#inImageRuntimeCode()}. The latter will return true when executing any native + * image, not just libgraal. */ - public static boolean isBuildingLibgraal() { - return Services.IS_BUILDING_NATIVE_IMAGE; + public static boolean isInLibgraal() { + return Services.IS_IN_NATIVE_IMAGE; } /** - * Returns true if code is executing in the context of executing libgraal. Note that this is - * more specific than {@link ImageInfo#inImageRuntimeCode()}. The latter will return true when - * executing any native image, not just libgraal. + * The set of services available in libgraal. */ - public static boolean isInLibgraal() { - return Services.IS_IN_NATIVE_IMAGE; + private static final Map, List> libgraalServices; + + @Platforms(Platform.HOSTED_ONLY.class) + private static Class loadClassOrNull(String name) { + try { + return GraalServices.class.getClassLoader().loadClass(name); + } catch (Throwable e) { + return null; + } } /** - * The set of services available in libgraal. This field is only non-null when - * {@link GraalServices} is loaded by the LibGraalClassLoader. + * Gets a name for the current architecture that is compatible with + * {@link Architecture#getName()}. */ - private static Map, List> libgraalServices; + @Platforms(Platform.HOSTED_ONLY.class) + private static String getJVMCIArch() { + String rawArch = getSavedProperty("os.arch"); + return switch (rawArch) { + case "x86_64" -> "AMD64"; + case "amd64" -> "AMD64"; + case "aarch64" -> "aarch64"; + case "riscv64" -> "riscv64"; + default -> throw new GraalError("Unknown or unsupported arch: %s", rawArch); + }; + } @Platforms(Platform.HOSTED_ONLY.class) - @ExcludeFromJacocoGeneratedReport("only called when building libgraal") - public static void setLibgraalServices(Map, List> services) { - GraalError.guarantee(libgraalServices == null, "Libgraal services must be set exactly once"); - GraalServices.libgraalServices = services; + @SuppressWarnings("unchecked") + private static void addProviders(String arch, Class service) { + List providers = (List) GraalServices.libgraalServices.computeIfAbsent(service, key -> new ArrayList<>()); + for (Object provider : ServiceLoader.load(service, GraalServices.class.getClassLoader())) { + if (provider instanceof ArchitectureSpecific as && !as.getArchitecture().equals(arch)) { + // Skip provider for another architecture + continue; + } + providers.add(provider); + } + } + + static { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + libgraalServices = new HashMap<>(); + String arch = getJVMCIArch(); + libgraal.getClassModuleMap().keySet().stream()// + .map(GraalServices::loadClassOrNull)// + .filter(c -> c != null && c.getAnnotation(LibGraalService.class) != null)// + .forEach(service -> addProviders(arch, service)); + } else { + libgraalServices = null; + } } private GraalServices() { @@ -104,6 +144,19 @@ public static Iterable load(Class service) { return load0(service); } + /** + * An escape hatch for calling {@link System#getProperties()} without falling afoul of + * {@code VerifySystemPropertyUsage}. + * + * @param justification explains why {@link #getSavedProperties()} cannot be used + */ + public static Properties getSystemProperties(String justification) { + if (justification == null || justification.isEmpty()) { + throw new IllegalArgumentException("non-empty justification required"); + } + return System.getProperties(); + } + /** * Gets an unmodifiable copy of the system properties in their state at system initialization * time. This method must be used instead of calling {@link Services#getSavedProperties()} @@ -114,7 +167,7 @@ public static Iterable load(Class service) { public static Map getSavedProperties() { if (inImageBuildtimeCode()) { // Avoid calling down to JVMCI native methods as they will fail to - // link in a copy of JVMCI loaded by the LibGraalClassLoader. + // link in a copy of JVMCI loaded by a LibGraalLoader. return jdk.internal.misc.VM.getSavedProperties(); } return Services.getSavedProperties(); @@ -284,7 +337,7 @@ public static String getExecutionID() { return Long.toString(ProcessHandle.current().pid()); } - private static final GlobalAtomicLong globalTimeStamp = new GlobalAtomicLong(0L); + private static final GlobalAtomicLong globalTimeStamp = new GlobalAtomicLong("GLOBAL_TIME_STAMP", 0L); /** * Gets a time stamp for the current process. This method will always return the same value for @@ -458,34 +511,4 @@ public static double fma(double a, double b, double c) { public static int getJavaUpdateVersion() { return Runtime.version().update(); } - - /** - * Notifies that the compiler is at a point where memory usage is expected to be minimal like - * after the completion of compilation. - * - * @param forceFullGC controls whether to explicitly perform a full GC - */ - public static void notifyLowMemoryPoint(boolean forceFullGC) { - notifyLowMemoryPoint(true, forceFullGC); - } - - /** - * Notifies that the compiler is at a point where memory usage is might have dropped - * significantly like after some major phase execution. - */ - public static void notifyLowMemoryPoint() { - notifyLowMemoryPoint(false, false); - } - - /** - * Notifies that the compiler is at a point where memory usage is expected to be relatively low - * (e.g., just before/after a compilation). The garbage collector might be able to make use of - * such a hint to optimize its performance. - * - * @param hintFullGC controls whether the hinted GC should be a full GC. - * @param forceFullGC controls whether to explicitly perform a full GC - */ - private static void notifyLowMemoryPoint(boolean hintFullGC, boolean forceFullGC) { - VMSupport.notifyLowMemoryPoint(hintFullGC, forceFullGC); - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/IsolateUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/IsolateUtil.java index 769b59941ac3..56b907406de3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/IsolateUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/IsolateUtil.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.serviceprovider; +import jdk.graal.compiler.core.common.LibGraalSupport; + /** * Utility methods that provide access to isolate details. */ @@ -33,22 +35,31 @@ public final class IsolateUtil { * Gets the address of the current isolate or 0 if this not an isolate-aware runtime. */ public static long getIsolateAddress() { - return VMSupport.getIsolateAddress(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + return libgraal.getIsolateAddress(); + } + return 0L; } /** - * Gets a non-zero identifier for the current isolate or 0 if this not an isolate-aware runtime. - * The returned value is guaranteed to be unique for the first {@code 2^64 - 1} isolates in the - * process. + * Gets an identifier for the current isolate. This will return 0 if + * {@link #getIsolateAddress()} returns 0. The returned value is guaranteed to be unique for the + * first {@code 2^64 - 1} isolates in the process. */ public static long getIsolateID() { - return VMSupport.getIsolateID(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + return libgraal.getIsolateID(); + } + return 0L; } /** * Gets a string identifying the current isolate. * - * If this is not an isolate-aware runtime, an empty string is returned. + * If this is not an isolate-aware runtime (i.e. {@link #getIsolateAddress()} returns 0), an + * empty string is returned. * * If {@code withAddress == true}, then * {@code String.format("%d@%x", getIsolateID(), getIsolateAddress())} is returned. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/VMSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/VMSupport.java deleted file mode 100644 index a84195a2932c..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/VMSupport.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.serviceprovider; - -/** - * Interface between the compiler and its Native Image based runtime (i.e. libgraal). - * - * The methods of this class are substituted by the libgraal implementation. - */ -public final class VMSupport { - /** - * @see IsolateUtil#getIsolateAddress - */ - public static long getIsolateAddress() { - return 0L; - } - - /** - * @see IsolateUtil#getIsolateID - */ - public static long getIsolateID() { - return 0L; - } - - /** - * Gets a scope that performs setup/cleanup actions around a libgraal compilation. - */ - public static AutoCloseable getCompilationRequestScope() { - return null; - } - - /** - * Notifies that a fatal error has occurred. - * - * @param message description of the error - * @param delayMS milliseconds to sleep before exiting the VM - */ - public static void fatalError(String message, int delayMS) { - - } - - /** - * Notifies libgraal when a Graal runtime is being started. - */ - public static void startupLibGraal() { - } - - /** - * Notifies libgraal when a Graal runtime is being shutdown. - */ - public static void shutdownLibGraal() { - } - - /** - * @param cbClassName name of class declaring the call back method - * @param cbMethodName name of the call back method - */ - public static void invokeShutdownCallback(String cbClassName, String cbMethodName) { - } - - /** - * @param hintFullGC controls whether the hinted GC should be a full GC. - * @param forceFullGC controls whether to explicitly perform a full GC - * @see GraalServices#notifyLowMemoryPoint() - */ - public static void notifyLowMemoryPoint(boolean hintFullGC, boolean forceFullGC) { - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java index 9e27499559bd..54db22da0d88 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java @@ -39,6 +39,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ThreadFactory; import java.util.function.Consumer; import org.graalvm.collections.EconomicMap; @@ -103,7 +104,6 @@ import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.site.Infopoint; import jdk.vm.ci.meta.Assumptions.Assumption; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ProfilingInfo; /** @@ -477,6 +477,15 @@ public void compileAST( compileAST(new TruffleCompilationWrapper(getOrCreateCompilerOptions(compilable), getDebugOutputDirectory(), Collections.emptyMap(), compilable, task, compilationId, listener), debug); } + /** + * Gets a factory to use for creating the {@link CompilationWatchDog} watcher thread. + * + * @see CompilationWatchDog#watch + */ + protected ThreadFactory getWatchDogThreadFactory() { + return null; + } + /** * Compiles a Truffle AST. If compilation succeeds, the AST will have compiled code associated * with it that can be executed instead of interpreting the AST. @@ -673,10 +682,6 @@ public TruffleTier getTruffleTier() { return truffleTier; } - public TruffleCompilable asCompilableTruffleAST(JavaConstant constant) { - return config.snippetReflection().asObject(TruffleCompilable.class, constant); - } - @Override public void onStuckCompilation(CompilationWatchDog watchDog, Thread watched, CompilationIdentifier compilation, StackTraceElement[] stackTrace, long stuckTime) { CompilationWatchDog.EventHandler.super.onStuckCompilation(watchDog, watched, compilation, stackTrace, stuckTime); @@ -771,7 +776,8 @@ protected Void handleException(Throwable t) { @SuppressWarnings("try") @Override protected Void performCompilation(DebugContext debug) { - try (CompilationWatchDog watch = CompilationWatchDog.watch(compilationId, debug.getOptions(), false, TruffleCompilerImpl.this)) { + ThreadFactory factory = getWatchDogThreadFactory(); + try (CompilationWatchDog watch = CompilationWatchDog.watch(compilationId, debug.getOptions(), false, TruffleCompilerImpl.this, factory)) { compileAST(this, debug); return null; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java index 6edf08da1e48..81db62ebc7f3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java @@ -33,9 +33,11 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.concurrent.ThreadFactory; import java.util.function.Supplier; import jdk.graal.compiler.core.GraalCompiler; +import jdk.graal.compiler.hotspot.HotSpotGraalServiceThread; import jdk.graal.compiler.truffle.host.TruffleHostEnvironment.TruffleRuntimeScope; import org.graalvm.collections.EconomicMap; @@ -141,6 +143,11 @@ protected void parseGraalOptions(String[] options, EconomicMap, Obj OptionsParser.parseOptions(options, values, OptionsParser.getOptionsLoader()); } + @Override + protected ThreadFactory getWatchDogThreadFactory() { + return HotSpotGraalServiceThread::new; + } + public static HotSpotTruffleCompilerImpl create(final TruffleCompilerRuntime runtime, Supplier openCanCallTruffleRuntimeScope) { OptionValues options = HotSpotGraalOptionValues.defaultOptions(); /* diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleSafepointLoweringSnippet.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleSafepointLoweringSnippet.java index 59ed27c9ada6..b2a3b2ec5dab 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleSafepointLoweringSnippet.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleSafepointLoweringSnippet.java @@ -60,7 +60,6 @@ import jdk.graal.compiler.truffle.nodes.TruffleSafepointNode; import jdk.graal.compiler.truffle.phases.TruffleSafepointInsertionPhase; import jdk.graal.compiler.word.Word; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -124,14 +123,14 @@ public void lower(TruffleSafepointNode node, LoweringTool tool) { static class TruffleHotSpotSafepointLoweringExtension implements DefaultHotSpotLoweringProvider.Extension { - @NativeImageReinitialize private Templates templates; + private Templates templates; private final HotSpotKnownTruffleTypes types; /** * Initialization deferred until the first Truffle compilation starts. */ - @NativeImageReinitialize private volatile Runnable deferredInit; + private volatile Runnable deferredInit; TruffleHotSpotSafepointLoweringExtension(HotSpotKnownTruffleTypes types) { this.types = types; diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 68982d10b4bc..d7674d55a569 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -133,7 +133,7 @@ def upx(args): ) mx_sdk_vm.register_graalvm_component(graalvm_sdk_component) -# SDK modules included the compiler is included +# SDK modules included if the compiler (jargraal) is included graal_sdk_compiler_component = mx_sdk_vm.GraalVmJreComponent( suite=_suite, name='Graal SDK Compiler', @@ -158,7 +158,7 @@ def upx(args): third_party_license_files=[], dependencies=['sdkc'], jar_distributions=[], - boot_jars=['sdk:NATIVEIMAGE'], + boot_jars=['sdk:NATIVEIMAGE', 'sdk:NATIVEIMAGE_LIBGRAAL'], stability="supported", ) mx_sdk_vm.register_graalvm_component(graalvm_sdk_native_image_component) diff --git a/sdk/mx.sdk/suite.py b/sdk/mx.sdk/suite.py index 37c5ab784c7d..ac5744c25674 100644 --- a/sdk/mx.sdk/suite.py +++ b/sdk/mx.sdk/suite.py @@ -436,6 +436,18 @@ "javaCompliance" : "11+", "workingSets" : "API,SDK", }, + + # Native Image API extensions for libgraal. + "org.graalvm.nativeimage.libgraal" : { + "subDir" : "src", + "sourceDirs" : ["src"], + "dependencies" : [ + "sdk:NATIVEIMAGE" + ], + "checkstyle" : "org.graalvm.word", + "javaCompliance" : "21+" + }, + "com.oracle.svm.core.annotate" : { "subDir" : "src", "sourceDirs" : ["src"], @@ -829,6 +841,32 @@ class UniversalDetector { }, }, + "NATIVEIMAGE_LIBGRAAL" : { + "subDir" : "src", + "dependencies" : [ + "org.graalvm.nativeimage.libgraal", + ], + "distDependencies" : ["NATIVEIMAGE"], + "javadocType": "api", + "moduleInfo" : { + "name" : "org.graalvm.nativeimage.libgraal", + "requires" : [ + "transitive org.graalvm.nativeimage", + ], + "exports" : [ + "org.graalvm.nativeimage.libgraal", + "org.graalvm.nativeimage.libgraal.hosted", + "org.graalvm.nativeimage.libgraal.impl to org.graalvm.nativeimage.builder", + ], + "uses" : [], + "opens" : [], + }, + "description" : "Native Image API extensions for libgraal.", + "maven": { + "tag": ["default", "public"], + }, + }, + "POLYGLOT_VERSION": { "type": "dir", "platformDependent": False, diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/OWNERS.toml b/sdk/src/org.graalvm.nativeimage.libgraal/OWNERS.toml new file mode 100644 index 000000000000..aa26b0f05cb0 --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/OWNERS.toml @@ -0,0 +1,11 @@ +[[rule]] +files = "*" +all = [ + "codrut.stancu@oracle.com", + "vojin.jovanovic@oracle.com", + "peter.hofer@oracle.com", + "christian.haeubl@oracle.com", + "paul.woegerer@oracle.com" + "doug.simon@oracle.com", + "tom.rodriguez@oracle.com" +] diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest new file mode 100644 index 000000000000..dc9525b4f04c --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest @@ -0,0 +1,31 @@ +#Signature file v4.1 +#Version + +CLSS public abstract interface org.graalvm.nativeimage.libgraal.LibGraalLoader +meth public abstract java.util.Map getClassModuleMap() + +CLSS public final org.graalvm.nativeimage.libgraal.LibGraalRuntime +meth public static long getIsolateID() +meth public static void notifyLowMemoryPoint(boolean) +meth public static void processReferences() +meth public static void fatalError(java.lang.String) +supr java.lang.Object + +CLSS public final org.graalvm.nativeimage.libgraal.hosted.GlobalData +meth public static java.util.function.Supplier createGlobal(long) +supr java.lang.Object + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable + anno 0 java.lang.Deprecated(boolean forRemoval=true, java.lang.String since="9") +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java new file mode 100644 index 000000000000..f82b1f09cc86 --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.libgraal; + +import java.util.Map; + +/** + * The class loader used to load the Graal and JVMCI classes compiled into libgraal implements this + * interface to provide extra information about the libgraal classes. + * + * @since 25 + */ +public interface LibGraalLoader { + + /** + * Gets a map from the {@linkplain Class#forName(String) name} of a class to the name of its + * enclosing module. There is one entry in the map for each class available for loading by this + * loader. + * + * @return an unmodifiable map + */ + Map getClassModuleMap(); +} diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java new file mode 100644 index 000000000000..a2a051e08170 --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.libgraal; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; + +import org.graalvm.nativeimage.ImageSingletons; + +import org.graalvm.nativeimage.libgraal.impl.LibGraalRuntimeSupport; + +/** + * LibGraal specific extensions to {@link org.graalvm.nativeimage}. + * + * @since 25 + */ +public final class LibGraalRuntime { + + /** + * Enqueues pending {@link Reference}s into their corresponding {@link ReferenceQueue}s and + * executes pending cleaners. + * + * If automatic reference handling is enabled, this method is a no-op. + */ + public static void processReferences() { + ImageSingletons.lookup(LibGraalRuntimeSupport.class).processReferences(); + } + + /** + * Notifies the runtime that the caller is at a point where the live set of objects is expected + * to just have decreased significantly and now is a good time for a partial or full collection. + * + * @param suggestFullGC if a GC is performed, then suggests a full GC is done. This is true when + * the caller believes the heap occupancy is close to the minimal set of live objects + * for Graal (e.g. after a compilation). + */ + public static void notifyLowMemoryPoint(boolean suggestFullGC) { + ImageSingletons.lookup(LibGraalRuntimeSupport.class).notifyLowMemoryPoint(suggestFullGC); + } + + /** + * Gets an identifier for the current isolate that is guaranteed to be unique for the first + * {@code 2^64 - 1} isolates in the process. + */ + public static long getIsolateID() { + return ImageSingletons.lookup(LibGraalRuntimeSupport.class).getIsolateID(); + } + + /** + * Called to signal a fatal, non-recoverable error. This method does not return or throw an + * exception but calls the HotSpot fatal crash routine that produces an hs-err crash log. + * + * @param message a description of the error condition + */ + public static void fatalError(String message) { + ImageSingletons.lookup(LibGraalRuntimeSupport.class).fatalError(message); + } + + private LibGraalRuntime() { + } +} diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java new file mode 100644 index 000000000000..18a2209f7a29 --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.libgraal.hosted; + +import org.graalvm.nativeimage.libgraal.impl.GlobalDataSupport; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import java.util.function.Supplier; + +/** + * Methods for creating initialized, off-heap data that is shared across all isolates in a process. + * + * @since 25 + */ +@Platforms(Platform.HOSTED_ONLY.class) +public final class GlobalData { + + /** + * Creates a pre-allocated and pre-initialized word that is off-heap. + * + * @param initialValue the initial value of the off-heap word + * @return a supplier of the address of the off-heap word + */ + public static Supplier createGlobal(long initialValue) { + return ImageSingletons.lookup(GlobalDataSupport.class).createGlobal(initialValue); + } + + private GlobalData() { + } +} diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java new file mode 100644 index 000000000000..15f3045a73ae --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/* + @ApiInfo( + group="Native Image LibGraal extensions" + ) + */ +/** + * Extensions to the GraalVM SDK Native Image API to customize building libgraal. Although these + * extensions contain public classes, they should only be used by the feature that builds libgraal. + * + * @since 25 + */ +package org.graalvm.nativeimage.libgraal.hosted; diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java new file mode 100644 index 000000000000..03b8a67033e8 --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.libgraal.impl; + +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; + +import java.util.function.Supplier; + +/** + * Interface for Native Image to implement {@link GlobalData}. + */ +public interface GlobalDataSupport { + + /** + * @see GlobalData#createGlobal(long) + */ + Supplier createGlobal(long initialValue); +} diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java new file mode 100644 index 000000000000..28910ffaf78f --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.libgraal.impl; + +import org.graalvm.nativeimage.libgraal.LibGraalRuntime; + +/** + * Interface for Native Image to implement {@link LibGraalRuntime}. + */ +public interface LibGraalRuntimeSupport { + + /** + * @see LibGraalRuntime#processReferences() + */ + void processReferences(); + + /** + * @see LibGraalRuntime#notifyLowMemoryPoint(boolean) + */ + void notifyLowMemoryPoint(boolean suggestFullGC); + + /** + * @see LibGraalRuntime#getIsolateID() + */ + long getIsolateID(); + + /** + * @see LibGraalRuntime#fatalError(String) + */ + void fatalError(String message); +} diff --git a/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java new file mode 100644 index 000000000000..77758b1c5e0b --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/* + @ApiInfo( + group="Native Image LibGraal extensions" + ) + */ +/** + * Extensions to the GraalVM SDK Native Image API to customize building libgraal. Although these + * extensions contain public classes, they should only be used by the feature that builds libgraal. + * + * @since 25 + */ +package org.graalvm.nativeimage.libgraal; diff --git a/sdk/src/org.graalvm.nativeimage/OWNERS.toml b/sdk/src/org.graalvm.nativeimage/OWNERS.toml new file mode 100644 index 000000000000..63a0b541595d --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage/OWNERS.toml @@ -0,0 +1,9 @@ +[[rule]] +files = "*" +all = [ + "codrut.stancu@oracle.com", + "vojin.jovanovic@oracle.com", + "peter.hofer@oracle.com", + "christian.haeubl@oracle.com", + "paul.woegerer@oracle.com" +] diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index b5d3a2ec5316..5c15c4d96208 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -1080,6 +1080,7 @@ meth public abstract java.util.Set reachableMethod CLSS public abstract interface org.graalvm.nativeimage.hosted.FieldValueTransformer meth public abstract java.lang.Object transform(java.lang.Object,java.lang.Object) +meth public boolean isAvailable() CLSS public final org.graalvm.nativeimage.hosted.RuntimeClassInitialization meth public !varargs static void initializeAtBuildTime(java.lang.Class[]) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/FieldValueTransformer.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/FieldValueTransformer.java index 04afbd762e9e..3a9f18bbb0a7 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/FieldValueTransformer.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/FieldValueTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -83,4 +83,13 @@ public interface FieldValueTransformer { * @since 22.3 */ Object transform(Object receiver, Object originalValue); + + /** + * Returns true when the value for this custom computation is available. + * + * @since 25 + */ + default boolean isAvailable() { + return true; + } } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/IsolateSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/IsolateSupport.java index 9b4112bc6a44..52555c04df81 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/IsolateSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/IsolateSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -58,12 +58,4 @@ public interface IsolateSupport { void detachThread(IsolateThread thread) throws IsolateException; void tearDownIsolate(IsolateThread thread) throws IsolateException; - - /** - * Gets an identifier for the current isolate that is guaranteed to be unique for the first - * {@code 2^64 - 1} isolates in the process. - * - * @return a non-zero value - */ - long getIsolateID(); } diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 65d06bad20db..551ceff88ae3 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -1471,11 +1471,14 @@ def _native_image_launcher_extra_jvm_args(): jlink=False, )) +# Jars copied to the /lib/graalvm of the libgraal GraalVM that +# are also added to the value of the `-imagecp` Native Image option when +# building libgraal. libgraal_jar_distributions = [ 'sdk:NATIVEBRIDGE', 'sdk:JNIUTILS', - 'compiler:LIBGRAAL_LOADER', - 'substratevm:LIBGRAAL_LIBRARY'] + 'compiler:LIBGRAAL', + 'compiler:LIBGRAAL_LOADER'] def allow_build_path_in_libgraal(): """ @@ -1505,33 +1508,15 @@ def prevent_build_path_in_libgraal(): return ['-H:NativeLinkerOption=-pdbaltpath:%_PDB%'] return [] -libgraal_features = [ - 'com.oracle.svm.graal.hotspot.libgraal.LibGraalFeature' -] - libgraal_build_args = [ - '--features=' + ','.join(libgraal_features), - - ## Pass via JVM args opening up of packages needed for image builder early on - '-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.hotspot=ALL-UNNAMED', - '-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.hotspot.libgraal=ALL-UNNAMED', - '-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED', - '-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.truffle=ALL-UNNAMED', - '-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.truffle.hotspot=ALL-UNNAMED', - '-J--add-exports=org.graalvm.truffle.compiler/com.oracle.truffle.compiler.hotspot.libgraal=ALL-UNNAMED', - '-J--add-exports=org.graalvm.truffle.compiler/com.oracle.truffle.compiler.hotspot=ALL-UNNAMED', - '-J--add-exports=org.graalvm.truffle.compiler/com.oracle.truffle.compiler=ALL-UNNAMED', - '-J--add-exports=org.graalvm.nativeimage/com.oracle.svm.core.annotate=ALL-UNNAMED', - '-J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.option=ALL-UNNAMED', - ## Packages used after option-processing can be opened by the builder (`-J`-prefix not needed) - # LibGraalFeature implements com.oracle.svm.core.feature.InternalFeature (needed to be able to instantiate LibGraalFeature) - '--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.feature=ALL-UNNAMED', - # Make ModuleSupport accessible to do the remaining opening-up in LibGraalFeature constructor - '--add-exports=org.graalvm.nativeimage.base/com.oracle.svm.util=ALL-UNNAMED', - # TruffleLibGraalJVMCIServiceLocator needs access to JVMCIServiceLocator - '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.services=ALL-UNNAMED', - - '--initialize-at-build-time=jdk.graal.compiler,org.graalvm.libgraal,com.oracle.truffle', + '--features=jdk.graal.compiler.libgraal.LibGraalFeature', + + # Need jdk.internal.module.Modules to do exporting + '-J--add-exports=java.base/jdk.internal.module=ALL-UNNAMED', + + # This is the truffle:TRUFFLE_COMPILER dependency that defines + # the Truffle compiler API. + '--initialize-at-build-time=com.oracle.truffle.compiler', '-H:+ReportExceptionStackTraces', @@ -1541,6 +1526,8 @@ def prevent_build_path_in_libgraal(): # If building on the console, use as many cores as available f'--parallelism={mx.cpu_count()}', ] if mx.is_interactive() else []) + svm_experimental_options([ + "-H:LibGraalClassLoader=jdk.graal.compiler.libgraal.loader.HostedLibGraalClassLoader", + "-Dlibgraal.module.path=${.}/../../../graalvm/libgraal.jar", '-H:-UseServiceLoaderFeature', '-H:+AllowFoldMethods', '-Dtruffle.TruffleRuntime=', @@ -1548,6 +1535,7 @@ def prevent_build_path_in_libgraal(): '-H:InitialCollectionPolicy=LibGraal', # Needed for initializing jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE. + # Remove after JDK-8346781. '-Djdk.vm.ci.services.aot=true', # These 2 arguments provide walkable call stacks for a crash in libgraal. diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index d6c3368db65e..a9ce2286a9c9 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -219,6 +219,7 @@ "sourceDirs": ["src"], "dependencies": [ "sdk:NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", "compiler:GRAAL", ], "requiresConcealed" : { @@ -1386,70 +1387,6 @@ "jacoco" : "exclude", }, - "com.oracle.svm.graal.hotspot" : { - "subDir": "src", - "sourceDirs" : [ - "src" - ], - "dependencies": [ - "sdk:JNIUTILS", - "compiler:GRAAL", - "SVM", - ], - "requiresConcealed" : { - "jdk.internal.vm.ci" : [ - "jdk.vm.ci.services", - "jdk.vm.ci.runtime", - "jdk.vm.ci.hotspot", - "jdk.vm.ci.meta" - ], - }, - "annotationProcessors": [ - "compiler:GRAAL_PROCESSOR", - ], - "checkstyle" : "com.oracle.svm.hosted", - "javaCompliance" : "21+", - "workingSets" : "SVM", - "jacoco" : "exclude", - }, - - "com.oracle.svm.graal.hotspot.libgraal" : { - "subDir": "src", - "sourceDirs" : [ - "src", - "resources", - ], - "dependencies": [ - "com.oracle.svm.graal.hotspot", - "sdk:NATIVEIMAGE", - "sdk:NATIVEBRIDGE", - "compiler:GRAAL", - "SVM", - ], - "requires": [ - "java.management", - "jdk.management", - ], - "requiresConcealed" : { - "java.base" : [ - "jdk.internal.misc", - ], - "jdk.internal.vm.ci" : [ - "jdk.vm.ci.services", - "jdk.vm.ci.runtime", - "jdk.vm.ci.code" - ], - }, - "annotationProcessors": [ - "compiler:GRAAL_PROCESSOR", - "truffle:TRUFFLE_LIBGRAAL_PROCESSOR", - ], - "checkstyle" : "com.oracle.svm.hosted", - "javaCompliance" : "21+", - "workingSets" : "SVM", - "jacoco" : "exclude", - }, - "com.oracle.svm.configure": { "subDir": "src", "sourceDirs": [ @@ -1777,6 +1714,7 @@ "transitive org.graalvm.nativeimage.pointsto", "org.graalvm.collections", "org.graalvm.truffle.compiler", + "org.graalvm.nativeimage.libgraal" ], "uses" : [ "org.graalvm.nativeimage.Platform", @@ -2036,21 +1974,6 @@ "maven" : False, }, - "LIBGRAAL_LIBRARY": { - "subDir": "src", - "description" : "LibGraal feature", - "javaCompliance" : "21+", - "dependencies": [ - "com.oracle.svm.graal.hotspot.libgraal", - ], - "distDependencies": [ - "SVM", - "sdk:JNIUTILS", - "sdk:NATIVEBRIDGE", - ], - "maven": False, - }, - # # Native Projects # @@ -2221,6 +2144,7 @@ "distDependencies": [ "compiler:GRAAL", "sdk:NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", ], "exclude": [ ], diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/AccessAdvisor.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/AccessAdvisor.java index 48d147d30aee..75e4f844707e 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/AccessAdvisor.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/AccessAdvisor.java @@ -152,7 +152,6 @@ private static void excludeInaccessiblePackages(HierarchyFilterNode rootNode) { rootNode.addOrGetChildren("com.oracle.truffle.**", ConfigurationFilter.Inclusion.Exclude); rootNode.addOrGetChildren("jdk.graal.compiler.**", ConfigurationFilter.Inclusion.Exclude); rootNode.addOrGetChildren("org.graalvm.compiler.**", ConfigurationFilter.Inclusion.Exclude); - rootNode.addOrGetChildren("org.graalvm.libgraal.**", ConfigurationFilter.Inclusion.Exclude); } public static HierarchyFilterNode copyBuiltinCallerFilterTree() { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index 0fcee811d5d4..2030984724cf 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; +import com.oracle.svm.core.jdk.SystemPropertiesSupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -129,6 +130,9 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { ImageSingletons.add(CommittedMemoryProvider.class, createCommittedMemoryProvider()); } + // If building libgraal, set system property showing gc algorithm + SystemPropertiesSupport.singleton().setLibGraalRuntimeProperty("gc", Heap.getHeap().getGC().getName()); + // Needed for the barrier set. access.registerAsUsed(Object[].class); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java index f32850b6a2fd..eb15ca7af9f3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java @@ -133,6 +133,10 @@ public static long getStartTimeNanos() { return startTimeNanos; } + /** + * Gets an identifier for the current isolate that is guaranteed to be unique for the first + * {@code 2^64 - 1} isolates in the process. + */ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) public static long getIsolateId() { assert isolateId >= 0; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 132e39a3744a..b8a9f5df9415 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -1389,4 +1389,7 @@ public static class TruffleStableOptions { throw UserError.invalidOptionValue(key, key.getValue(), "Mapping the image heap with mremap() is only supported on Linux."); } }); + + @Option(help = "file:doc-files/LibGraalClassLoader.txt")// + public static final HostedOptionKey LibGraalClassLoader = new HostedOptionKey<>(""); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/GlobalLongSupplier.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/GlobalLongSupplier.java new file mode 100644 index 000000000000..8e105e0c7e6a --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/GlobalLongSupplier.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.c; + +import jdk.graal.compiler.word.Word; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; +import org.graalvm.word.PointerBase; + +import java.util.function.Supplier; + +/** + * @see GlobalData#createGlobal(long) + */ +public class GlobalLongSupplier implements Supplier { + private final CGlobalData data; + + public GlobalLongSupplier(long initialValue) { + this.data = CGlobalDataFactory.createWord(Word.unsigned(initialValue), null, true); + } + + @Override + public Long get() { + return data.get().rawValue(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java index e0dc0b6165eb..fb88cfbd710c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java @@ -26,8 +26,6 @@ import java.util.List; -import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.c.CGlobalDataFactory; import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.Isolate; import org.graalvm.nativeimage.IsolateThread; @@ -38,7 +36,6 @@ import org.graalvm.nativeimage.c.type.CCharPointerPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.impl.IsolateSupport; -import org.graalvm.word.Pointer; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.c.function.CEntryPointNativeFunctions.IsolateThreadPointer; @@ -50,8 +47,6 @@ import com.oracle.svm.core.os.MemoryProtectionProvider; import com.oracle.svm.core.os.MemoryProtectionProvider.UnsupportedDomainException; -import static org.graalvm.word.LocationIdentity.ANY_LOCATION; - @AutomaticallyRegisteredImageSingleton(IsolateSupport.class) public final class IsolateSupportImpl implements IsolateSupport { private static final String ISOLATES_DISABLED_MESSAGE = "Spawning of multiple isolates is disabled, use " + @@ -172,31 +167,4 @@ private static void throwOnError(int code) { throw new IsolateException(message); } } - - private static final CGlobalData nextIsolateId = CGlobalDataFactory.createWord((Pointer) Word.unsigned(1L)); - - private volatile long isolateId = 0; - - @Override - public long getIsolateID() { - if (isolateId == 0) { - synchronized (this) { - if (isolateId == 0) { - Pointer p = nextIsolateId.get(); - long value; - long nextValue; - do { - value = p.readLong(0); - nextValue = value + 1; - if (nextValue == 0) { - // Avoid setting id to reserved 0 value after long integer overflow - nextValue = 1; - } - } while (p.compareAndSwapLong(0, value, nextValue, ANY_LOCATION) != value); - isolateId = value; - } - } - } - return isolateId; - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/LibGraalClassLoader.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/LibGraalClassLoader.txt new file mode 100644 index 000000000000..17c5d6ad420b --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/LibGraalClassLoader.txt @@ -0,0 +1,10 @@ +Specify the fully qualified name of a class that implements org.graalvm.nativeimage.libgraal.LibGraalLoader. + +This option is only supported for building the libgraal shared library. + +The named class is instantiated via the default constructor. +It affects image building as follows: + + 1. The custom loader is used to lookup Feature implementations passed via the --features option. + 2. All @CEntryPoint definitions in classes loaded by the custom loader are processed. + 3. All @TargetClass substitutions in classes loaded by the custom loader are processed. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java index 2beb2e5b7fb3..3f6390d7920e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java @@ -38,6 +38,7 @@ public interface FieldValueTransformerWithAvailability extends FieldValueTransfo /** * Returns true when the value for this custom computation is available. */ + @Override boolean isAvailable(); /** diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JVMCISubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JVMCISubstitutions.java index 768328a0a731..e2a77acd26ba 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JVMCISubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JVMCISubstitutions.java @@ -51,15 +51,6 @@ final class Target_jdk_vm_ci_services_Services { public static boolean IS_IN_NATIVE_IMAGE = true; // Checkstyle: resume - /** - * Ensure field returns false if seen by the analysis. - */ - // Checkstyle: stop - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// - public static boolean IS_BUILDING_NATIVE_IMAGE = false; - // Checkstyle: resume - /** * Redirect to {@link SystemPropertiesSupport#singleton()}. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RuntimeSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RuntimeSupport.java index bc95bf523cba..a07ad24ac362 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RuntimeSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RuntimeSupport.java @@ -44,6 +44,7 @@ @AutomaticallyRegisteredImageSingleton({VMRuntimeSupport.class, RuntimeSupport.class}) public final class RuntimeSupport implements VMRuntimeSupport { + @FunctionalInterface public interface Hook { void execute(boolean isFirstIsolate); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemPropertiesSupport.java index 6c78e2da84c6..44f5cf8025fb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemPropertiesSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.jdk; +import static jdk.graal.compiler.core.common.LibGraalSupport.LIBGRAAL_SETTING_PROPERTY_PREFIX; import static jdk.graal.compiler.nodes.extended.MembarNode.FenceKind.STORE_STORE; import java.util.ArrayList; @@ -35,10 +36,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; +import com.oracle.svm.core.SubstrateOptions; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.RuntimeSystemProperties; import org.graalvm.nativeimage.impl.RuntimeSystemPropertiesSupport; import com.oracle.svm.core.SubstrateUtil; @@ -290,6 +293,18 @@ private synchronized void initializeAllProperties() { allPropertiesInitialized = true; } + /** + * If the current image being built is libgraal, sets a runtime system property used to describe + * some aspect of the libgraal image configuration. + * + * @see jdk.graal.compiler.core.common.LibGraalSupport#LIBGRAAL_SETTING_PROPERTY_PREFIX + */ + public void setLibGraalRuntimeProperty(String name, String value) { + if (!SubstrateOptions.LibGraalClassLoader.getValue().isEmpty()) { + RuntimeSystemProperties.register(LIBGRAAL_SETTING_PROPERTY_PREFIX + name, value); + } + } + private void ensurePropertyInitialized(String key) { if (allPropertiesInitialized) { return; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIInvocationInterface.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIInvocationInterface.java index a3b11aa67ded..1d37283146f4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIInvocationInterface.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIInvocationInterface.java @@ -24,8 +24,8 @@ */ package com.oracle.svm.core.jni.functions; +import com.oracle.svm.core.Isolates; import jdk.graal.compiler.word.Word; -import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CEntryPoint; @@ -35,7 +35,6 @@ import org.graalvm.nativeimage.c.type.CCharPointerPointer; import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.WordPointer; -import org.graalvm.nativeimage.impl.IsolateSupport; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; @@ -204,8 +203,8 @@ static int enter(JNIJavaVMPointer vmBuf, JNIEnvironmentPointer penv, JNIJavaVMIn | | 0-terminated C string describing the error if a description is available, | | | otherwise extraInfo is set to null. | |--------------------|-----------------------------------------------------------------------------------| - | _javavm_id | extraInfo is a "unsigned long*" value. | - | | A non-zero identifier for the current isolate that is guaranteed to be unique for | + | _javavm_id | extraInfo is a "jlong*" value. | + | | An identifier for the current isolate that is guaranteed to be unique for | | | the first 2^64 - 1 isolates in the process is returned in *value. | |--------------------|-----------------------------------------------------------------------------------| * @@ -393,7 +392,7 @@ private static int finishInitialization0(JNIJavaVMPointer vmBuf, JNIEnvironmentP JNIJavaVM javaVm = JNIFunctionTables.singleton().getGlobalJavaVM(); JNIJavaVMList.addJavaVM(javaVm); if (javaVmIdPointer.isNonNull()) { - long javaVmId = ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); + long javaVmId = Isolates.getIsolateId(); javaVmIdPointer.write(Word.pointer(javaVmId)); } RuntimeSupport.getRuntimeSupport().addTearDownHook(new RuntimeSupport.Hook() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java new file mode 100644 index 000000000000..67c1cddf93fd --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.libgraal; + +import com.oracle.svm.core.Isolates; + +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.util.VMError; + +import org.graalvm.nativeimage.libgraal.impl.LibGraalRuntimeSupport; + +@AutomaticallyRegisteredImageSingleton({LibGraalRuntimeSupport.class}) +public final class LibGraalRuntimeSupportImpl implements LibGraalRuntimeSupport { + + @Override + public void processReferences() { + Heap.getHeap().doReferenceHandling(); + } + + @Override + public void notifyLowMemoryPoint(boolean suggestFullGC) { + Heap.getHeap().getGC().collectionHint(suggestFullGC); + } + + @Override + public long getIsolateID() { + return Isolates.getIsolateId(); + } + + @Override + public void fatalError(String message) { + throw VMError.shouldNotReachHere(message); + } +} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalCompilerSupport.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalCompilerSupport.java deleted file mode 100644 index d2985195e875..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalCompilerSupport.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.util.ImageHeapMap; - -/** - * Holds data that is pre-computed during native image generation and accessed at run time during a - * Graal compilation. - */ -public class LibGraalCompilerSupport { - - public final EconomicMap, Object> nodeClasses = ImageHeapMap.create(); - public final EconomicMap, Object> instructionClasses = ImageHeapMap.create(); - - protected EconomicMap, Object> basePhaseStatistics = ImageHeapMap.create(); - protected EconomicMap, Object> lirPhaseStatistics = ImageHeapMap.create(); - - @Platforms(Platform.HOSTED_ONLY.class) - static void registerStatistics(Class phaseSubClass, EconomicMap, Object> cache, Object newStatistics) { - assert !cache.containsKey(phaseSubClass); - cache.put(phaseSubClass, newStatistics); - } - - public static LibGraalCompilerSupport get() { - return ImageSingletons.lookup(LibGraalCompilerSupport.class); - } - - public EconomicMap, Object> getBasePhaseStatistics() { - return basePhaseStatistics; - } - - public EconomicMap, Object> getLirPhaseStatistics() { - return lirPhaseStatistics; - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java deleted file mode 100644 index 6f8704ffd352..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.jniutils.HSObject; -import org.graalvm.jniutils.JNI; -import org.graalvm.jniutils.JNI.JByteArray; -import org.graalvm.jniutils.JNI.JClass; -import org.graalvm.jniutils.JNI.JNIEnv; -import org.graalvm.jniutils.JNI.JObject; -import org.graalvm.jniutils.JNI.JObjectArray; -import org.graalvm.jniutils.JNI.JString; -import org.graalvm.jniutils.JNIExceptionWrapper; -import org.graalvm.jniutils.JNIMethodScope; -import org.graalvm.jniutils.JNIUtil; -import org.graalvm.nativebridge.BinaryOutput; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Isolate; -import org.graalvm.nativeimage.IsolateThread; -import org.graalvm.nativeimage.ObjectHandles; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.c.function.CEntryPoint; -import org.graalvm.nativeimage.c.function.CEntryPoint.Builtin; -import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateContext; -import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateThreadContext; -import org.graalvm.nativeimage.c.type.CLongPointer; -import org.graalvm.nativeimage.c.type.CTypeConversion; -import org.graalvm.nativeimage.impl.IsolateSupport; -import org.graalvm.word.PointerBase; - -import com.oracle.svm.core.heap.Heap; -import com.oracle.svm.core.heap.UnknownObjectField; -import com.oracle.svm.core.option.RuntimeOptionValues; -import com.oracle.svm.core.option.XOptions; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.graal.hotspot.LibGraalJNIMethodScope; -import com.oracle.svm.util.ClassUtil; -import com.oracle.truffle.compiler.TruffleCompilerOptionDescriptor; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleToLibGraal; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleToLibGraal.Id; -import com.sun.management.ThreadMXBean; - -import jdk.graal.compiler.hotspot.libgraal.BuildTime; -import jdk.graal.compiler.hotspot.libgraal.RunTime; -import jdk.graal.compiler.options.OptionDescriptor; -import jdk.graal.compiler.options.OptionDescriptors; -import jdk.graal.compiler.options.OptionDescriptorsMap; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.options.OptionsParser; -import jdk.graal.compiler.word.Word; -import jdk.internal.misc.Unsafe; - -/** - * Encapsulates {@link CEntryPoint} implementations as well as method handles for invoking LibGraal - * and JVMCI functionality via {@link MethodHandle}s. The method handles (initialized by - * {@link BuildTime#getRuntimeHandles()}) are only invoked in static methods which allows Native - * Image to fold them to direct calls to the method handle targets. - */ -final class LibGraalEntryPoints { - - private final MethodHandle getJNIEnv; - private final MethodHandle getSavedProperty; - private final MethodHandle ttyPrintf; - private final MethodHandle compileMethod; - private final MethodHandle hashConstantOopFields; - private final MethodHandle attachCurrentThread; - private final MethodHandle detachCurrentThread; - - /** - * Returns the {@link LibGraalEntryPoints} instance registered in the {@link ImageSingletons}. - */ - private static LibGraalEntryPoints singleton() { - return ImageSingletons.lookup(LibGraalEntryPoints.class); - } - - @Platforms(Platform.HOSTED_ONLY.class) - LibGraalEntryPoints(Map handles) { - this.getJNIEnv = handles.get("getJNIEnv"); - this.getSavedProperty = handles.get("getSavedProperty"); - this.ttyPrintf = handles.get("ttyPrintf"); - this.compileMethod = handles.get("compileMethod"); - this.hashConstantOopFields = handles.get("hashConstantOopFields"); - this.attachCurrentThread = handles.get("attachCurrentThread"); - this.detachCurrentThread = handles.get("detachCurrentThread"); - } - - /** - * Calls {@code jdk.graal.compiler.hotspot.libgraal.RunTime#getJNIEnv()}. - */ - static JNI.JNIEnv getJNIEnv() { - try { - long raw = (long) singleton().getJNIEnv.invoke(); - return Word.unsigned(raw); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - /** - * Calls {@code jdk.graal.compiler.serviceprovider.GraalServices#getSavedProperty(String)}. - */ - static String getSavedProperty(String name) { - try { - return (String) singleton().getSavedProperty.invoke(name); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - /** - * Calls {@link RunTime#attachCurrentThread}. - */ - static boolean attachCurrentThread(boolean daemon, long[] isolate) { - try { - return (boolean) singleton().attachCurrentThread.invoke(daemon, isolate); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - /** - * Calls {@link RunTime#detachCurrentThread}. - */ - static boolean detachCurrentThread(boolean release) { - try { - return (boolean) singleton().detachCurrentThread.invoke(release); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - /** - * Calls {@code jdk.graal.compiler.debug.TTY#printf(String, Object...)}. - */ - static void ttyPrintf(String format, Object... args) { - try { - singleton().ttyPrintf.invoke(format, args); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - /** - * The implementation of - * {@code jdk.graal.compiler.hotspot.test.LibGraalCompilationDriver#compileMethodInLibgraal}. - * Calls {@link RunTime#compileMethod}. - * - * @param methodHandle the method to be compiled. This is a handle to a - * {@code HotSpotResolvedJavaMethod} in HotSpot's heap. A value of 0L can be passed - * to use this method for the side effect of initializing a - * {@code HotSpotGraalCompiler} instance without doing any compilation. - * @param useProfilingInfo specifies if profiling info should be used during the compilation - * @param installAsDefault specifies if the compiled code should be installed for the - * {@code Method*} associated with {@code methodHandle} - * @param printMetrics specifies if global metrics should be printed and reset - * @param optionsAddress native byte buffer storing a serialized {@code OptionValues} object - * @param optionsSize the number of bytes in the buffer - * @param optionsHash hash code of bytes in the buffer (computed with - * {@link Arrays#hashCode(byte[])}) - * @param stackTraceAddress a native buffer in which a serialized stack trace can be returned. - * The caller will only read from this buffer if this method returns 0. A returned - * serialized stack trace is returned in this buffer with the following format: - * - *
-     *               struct {
-     *                   int   length;
-     *                   byte  data[length]; // Bytes from a stack trace printed to a ByteArrayOutputStream.
-     *               }
-     *            
- * - * where {@code length} is truncated to {@code stackTraceCapacity - 4} if necessary - * - * @param stackTraceCapacity the size of the stack trace buffer - * @param timeAndMemBufferAddress 16-byte native buffer to store result of time and memory - * measurements of the compilation - * @param profilePathBufferAddress native buffer containing a 0-terminated C string representing - * {@code Options#LoadProfiles} path. - * @return a handle to a {@code InstalledCode} in HotSpot's heap or 0 if compilation failed - */ - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_test_LibGraalCompilationDriver_compileMethodInLibgraal", include = LibGraalFeature.IsEnabled.class) - private static long compileMethod(JNIEnv jniEnv, - PointerBase jclass, - @IsolateThreadContext long isolateThreadAddress, - long methodHandle, - boolean useProfilingInfo, - boolean installAsDefault, - boolean printMetrics, - boolean eagerResolving, - long optionsAddress, - int optionsSize, - int optionsHash, - long stackTraceAddress, - int stackTraceCapacity, - long timeAndMemBufferAddress, - long profilePathBufferAddress) { - try (JNIMethodScope jniScope = new JNIMethodScope("compileMethod", jniEnv)) { - String profileLoadPath; - if (profilePathBufferAddress > 0) { - profileLoadPath = CTypeConversion.toJavaString(Word.pointer(profilePathBufferAddress)); - } else { - profileLoadPath = null; - } - BiConsumer timeAndMemConsumer; - Supplier currentThreadAllocatedBytes; - if (timeAndMemBufferAddress != 0) { - timeAndMemConsumer = (timeSpent, bytesAllocated) -> { - Unsafe.getUnsafe().putLong(timeAndMemBufferAddress, bytesAllocated); - Unsafe.getUnsafe().putLong(timeAndMemBufferAddress + 8, timeSpent); - }; - ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); - currentThreadAllocatedBytes = () -> threadMXBean.getCurrentThreadAllocatedBytes(); - } else { - timeAndMemConsumer = null; - currentThreadAllocatedBytes = null; - } - - return (long) singleton().compileMethod.invoke(methodHandle, useProfilingInfo, - installAsDefault, printMetrics, eagerResolving, - optionsAddress, optionsSize, optionsHash, - profileLoadPath, timeAndMemConsumer, currentThreadAllocatedBytes); - } catch (Throwable t) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - t.printStackTrace(new PrintStream(baos)); - byte[] stackTrace = baos.toByteArray(); - int length = Math.min(stackTraceCapacity - Integer.BYTES, stackTrace.length); - Unsafe.getUnsafe().putInt(stackTraceAddress, length); - Unsafe.getUnsafe().copyMemory(stackTrace, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, stackTraceAddress + Integer.BYTES, length); - return 0L; - } finally { - /* - * libgraal doesn't use a dedicated reference handler thread, so we trigger the - * reference handling manually when a compilation finishes. - */ - doReferenceHandling(); - } - } - - @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_test_LibGraalCompilerTest_hashConstantOopFields", include = LibGraalFeature.IsEnabled.class) - @SuppressWarnings({"unused", "try"}) - private static long hashConstantOopFields(JNIEnv jniEnv, - PointerBase jclass, - @IsolateThreadContext long isolateThreadAddress, - long typeHandle, - boolean useScope, - int iterations, - int oopsPerIteration, - boolean verbose) { - try (JNIMethodScope scope = new JNIMethodScope("hashConstantOopFields", jniEnv)) { - Runnable doReferenceHandling = LibGraalEntryPoints::doReferenceHandling; - return (long) singleton().hashConstantOopFields.invoke(typeHandle, useScope, iterations, oopsPerIteration, verbose, doReferenceHandling); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(jniEnv, t); - return 0; - } - } - - /** - * Since reference handling is synchronous in libgraal, explicitly perform it here and then run - * any code which is expecting to process a reference queue to let it clean up. - */ - static void doReferenceHandling() { - Heap.getHeap().doReferenceHandling(); - synchronized (LibGraalJVMCISubstitutions.Target_jdk_vm_ci_hotspot_Cleaner.class) { - LibGraalJVMCISubstitutions.Target_jdk_vm_ci_hotspot_Cleaner.clean(); - } - } - - /** - * Options configuring the VM in which libgraal is running. - */ - @UnknownObjectField(fullyQualifiedTypes = "org.graalvm.collections.EconomicMapImpl") // - static EconomicMap vmOptionDescriptors = EconomicMap.create(); - - static void initializeOptions(Map settings) { - EconomicMap nonXSettings = processXOptions(settings); - EconomicMap, Object> vmOptionValues = OptionValues.newOptionMap(); - Iterable vmOptionLoader = List.of(new OptionDescriptorsMap(vmOptionDescriptors)); - OptionsParser.parseOptions(nonXSettings, vmOptionValues, vmOptionLoader); - RuntimeOptionValues.singleton().update(vmOptionValues); - } - - /** - * Extracts and processes the {@link XOptions} in {@code settings}. - * - * @return the entries in {@code settings} that do not correspond to {@link XOptions} - */ - private static EconomicMap processXOptions(Map settings) { - EconomicMap nonXSettings = EconomicMap.create(settings.size()); - for (var e : settings.entrySet()) { - String key = e.getKey(); - String value = e.getValue(); - if (key.startsWith("X") && value.isEmpty()) { - String xarg = key.substring(1); - if (XOptions.setOption(xarg)) { - continue; - } - } - nonXSettings.put(key, value); - } - return nonXSettings; - } - - static void printOptions(PrintStream out, String prefix) { - RuntimeOptionValues vmOptions = RuntimeOptionValues.singleton(); - Iterable vmOptionLoader = Collections.singletonList(new OptionDescriptorsMap(vmOptionDescriptors)); - vmOptions.printHelp(vmOptionLoader, out, prefix, true); - } -} - -final class LibGraalScopeEntryPoints { - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_getIsolateThreadIn", builtin = Builtin.GET_CURRENT_THREAD) - private static native IsolateThread getIsolateThreadIn(PointerBase env, PointerBase hsClazz, @IsolateContext Isolate isolate); - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_attachThreadTo", builtin = Builtin.ATTACH_THREAD) - static native long attachThreadTo(PointerBase env, PointerBase hsClazz, @IsolateContext long isolate); - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_detachThreadFrom", builtin = Builtin.DETACH_THREAD) - static native void detachThreadFrom(PointerBase env, PointerBase hsClazz, @IsolateThreadContext long isolateThreadAddress); - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalScope_getIsolateId") - @SuppressWarnings("unused") - public static long getIsolateId(PointerBase env, PointerBase jclass, @IsolateThreadContext long isolateThreadAddress) { - return ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); - } -} - -final class LibGraalTruffleToLibGraalEntryPoints { - - private static volatile int lastJavaPCOffset = -1; - - /* - * Each of the following MethodHandle fields corresponds to a TruffleToLibGraal.Id value. The - * naming convention requires that each field name match the method name returned by - * TruffleToLibGraal.Id.getMethodName(). Additionally, the GraalEntryPoints method that the - * MethodHandle references must also follow this naming convention. The null MethodHandle values - * are overwritten reflectively in the constructor - */ - private final MethodHandle initializeIsolate = null; - private final MethodHandle registerRuntime = null; - private final MethodHandle initializeRuntime = null; - private final MethodHandle newCompiler = null; - private final MethodHandle initializeCompiler = null; - private final MethodHandle getCompilerConfigurationFactoryName = null; - private final MethodHandle doCompile = null; - private final MethodHandle shutdown = null; - private final MethodHandle installTruffleCallBoundaryMethod = null; - private final MethodHandle installTruffleReservedOopMethod = null; - private final MethodHandle pendingTransferToInterpreterOffset = null; - private final MethodHandle getSuppliedString = null; - private final MethodHandle getNodeCount = null; - private final MethodHandle getNodeTypes = null; - private final MethodHandle getCompilationId = null; - private final MethodHandle getTargetCodeSize = null; - private final MethodHandle getTotalFrameSize = null; - private final MethodHandle getExceptionHandlersCount = null; - private final MethodHandle getInfopointsCount = null; - private final MethodHandle getInfopoints = null; - private final MethodHandle listCompilerOptions = null; - private final MethodHandle compilerOptionExists = null; - private final MethodHandle validateCompilerOption = null; - private final MethodHandle getMarksCount = null; - private final MethodHandle getDataPatchesCount = null; - private final MethodHandle purgePartialEvaluationCaches = null; - private final MethodHandle getCompilerVersion = null; - - private final MethodHandle getCurrentJavaThread; - private final MethodHandle getLastJavaPCOffset; - - @Platforms(Platform.HOSTED_ONLY.class) - LibGraalTruffleToLibGraalEntryPoints(Lookup libgraalLookup, Class graalEntryPoints) { - try { - Map graalMethodByName = Arrays.stream(graalEntryPoints.getDeclaredMethods()).// - filter((m) -> Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())).// - collect(Collectors.toMap(Method::getName, (m) -> m)); - /* - * hostMethodByName is used solely to ensure that all delegation methods have been - * implemented. - */ - Set hostMethodByName = Arrays.stream(getClass().getDeclaredMethods()).// - filter((m) -> Modifier.isStatic(m.getModifiers()) && m.getAnnotation(TruffleToLibGraal.class) != null).// - map(Method::getName).// - collect(Collectors.toSet()); - for (Id id : Id.values()) { - String methodName = id.getMethodName(); - Method method = graalMethodByName.get(methodName); - if (method == null) { - throw VMError.shouldNotReachHere("Missing libgraal entry method %s.%s corresponding to TruffleToLibGraal.Id.%s. " + - "To resolve this, add `public static %s()` in %s, where the and correspond to TruffleToLibGraalCalls.%s.", - ClassUtil.getUnqualifiedName(graalEntryPoints), methodName, id, methodName, graalEntryPoints.getName(), methodName); - } - if (!hostMethodByName.contains(methodName)) { - throw VMError.shouldNotReachHere("Missing C entry point method %s.%s corresponding to TruffleToLibGraal.Id.%s. " + - "To resolve this, add `@CEntryPoint(\"Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_%s\") " + - "@TruffleToLibGraal(Id.%s) static %s(JNIEnv env, JClass jclass, @IsolateThreadContext long isolateThreadAddress, " + - ")` in %s, where the and correspond to TruffleToLibGraalCalls.%s. " + - "Use a MethodHandle to delegate to %s.%s.", - ClassUtil.getUnqualifiedName(getClass()), methodName, id, methodName, id, methodName, getClass().getName(), methodName, - graalEntryPoints.getName(), methodName); - } - Field methodHandleField; - try { - methodHandleField = getClass().getDeclaredField(methodName); - } catch (NoSuchFieldException nsf) { - throw VMError.shouldNotReachHere("Missing field %s.%s corresponding to TruffleToLibGraal.Id.%s. " + - "To resolve this, add `private final MethodHandle %s = null;` to %s.", - ClassUtil.getUnqualifiedName(getClass()), methodName, id, methodName, getClass().getName()); - } - methodHandleField.setAccessible(true); - methodHandleField.set(this, libgraalLookup.unreflect(method)); - } - Method m = graalMethodByName.get("getCurrentJavaThread"); - if (m == null) { - throw VMError.shouldNotReachHere("Missing libgraal entry method %s.getCurrentJavaThread.", ClassUtil.getUnqualifiedName(graalEntryPoints)); - } - getCurrentJavaThread = libgraalLookup.unreflect(m); - m = graalMethodByName.get("getLastJavaPCOffset"); - if (m == null) { - throw VMError.shouldNotReachHere("Missing libgraal entry method %s.getLastJavaPCOffset.", ClassUtil.getUnqualifiedName(graalEntryPoints)); - } - getLastJavaPCOffset = libgraalLookup.unreflect(m); - } catch (ReflectiveOperationException e) { - throw VMError.shouldNotReachHere(e); - } - } - - private static JNIMethodScope openScope(Enum id, JNIEnv env) throws Throwable { - Objects.requireNonNull(id, "Id must be non null."); - String scopeName = ClassUtil.getUnqualifiedName(LibGraalTruffleToLibGraalEntryPoints.class) + "::" + id; - int offset = lastJavaPCOffset; - if (offset == -1) { - offset = (int) singleton().getLastJavaPCOffset.invoke(); - lastJavaPCOffset = offset; - } - CLongPointer currentThreadLastJavaPCOffset = (CLongPointer) Word.unsigned((long) singleton().getCurrentJavaThread.invoke()).add(offset); - PointerBase javaFrameAnchor = Word.pointer(currentThreadLastJavaPCOffset.read()); - return LibGraalJNIMethodScope.open(scopeName, env, javaFrameAnchor.isNonNull()); - } - - private static LibGraalTruffleToLibGraalEntryPoints singleton() { - return ImageSingletons.lookup(LibGraalTruffleToLibGraalEntryPoints.class); - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeIsolate") - @TruffleToLibGraal(Id.InitializeIsolate) - public static void initializeIsolate(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JClass runtimeClass) { - try (JNIMethodScope s = openScope(Id.InitializeIsolate, env)) { - TruffleFromLibGraalStartPoints.initializeJNI(runtimeClass); - singleton().initializeIsolate.invoke(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_registerRuntime") - @TruffleToLibGraal(Id.RegisterRuntime) - public static boolean registerRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JObject truffleRuntime) { - try (JNIMethodScope s = openScope(Id.RegisterRuntime, env)) { - return (boolean) singleton().registerRuntime.invoke(JNIUtil.NewWeakGlobalRef(env, truffleRuntime, "TruffleCompilerRuntime").rawValue()); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return false; - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeRuntime") - @TruffleToLibGraal(Id.InitializeRuntime) - public static long initializeRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, - JObject truffleRuntime, JClass hsClassLoaderDelegate) { - try (JNIMethodScope s = openScope(Id.InitializeRuntime, env)) { - HSObject hsHandle = new HSObject(env, truffleRuntime, true, false); - Object hsTruffleRuntime = singleton().initializeRuntime.invoke(hsHandle, hsClassLoaderDelegate.rawValue()); - return LibGraalObjectHandles.create(hsTruffleRuntime); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0L; - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_newCompiler") - @TruffleToLibGraal(Id.NewCompiler) - public static long newCompiler(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long truffleRuntimeHandle) { - try (JNIMethodScope s = openScope(Id.NewCompiler, env)) { - Object truffleRuntime = LibGraalObjectHandles.resolve(truffleRuntimeHandle, Object.class); - Object compiler = singleton().newCompiler.invoke(truffleRuntime); - return LibGraalObjectHandles.create(compiler); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @SuppressWarnings("unused") - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeCompiler") - @TruffleToLibGraal(Id.InitializeRuntime) - public static void initializeCompiler(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long compilerHandle, JObject hsCompilable, - boolean firstInitialization) { - try (JNIMethodScope scope = openScope(Id.InitializeCompiler, env)) { - Object compiler = LibGraalObjectHandles.resolve(compilerHandle, Object.class); - singleton().initializeCompiler.invoke(compiler, new HSObject(scope, hsCompilable), firstInitialization); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getCompilerConfigurationFactoryName") - @TruffleToLibGraal(Id.GetCompilerConfigurationFactoryName) - public static JString getCompilerConfigurationFactoryName(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long truffleRuntimeHandle) { - try { - JNIMethodScope scope = openScope(Id.GetCompilerConfigurationFactoryName, env); - try (JNIMethodScope s = scope) { - String name = (String) singleton().getCompilerConfigurationFactoryName.invoke(); - scope.setObjectResult(JNIUtil.createHSString(env, name)); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_doCompile") - @TruffleToLibGraal(Id.DoCompile) - public static void doCompile(JNIEnv env, - JClass hsClazz, - @IsolateThreadContext long isolateThreadAddress, - long compilerHandle, - JObject hsTask, - JObject hsCompilable, - JObject hsListener) { - try (JNIMethodScope scope = openScope(Id.DoCompile, env)) { - Object compiler = LibGraalObjectHandles.resolve(compilerHandle, Object.class); - Object taskHsHandle = hsTask.isNull() ? null : new HSObject(scope, hsTask); - Object compilableHsHandle = new HSObject(scope, hsCompilable); - Object listenerHsHandle = hsListener.isNull() ? null : new HSObject(scope, hsListener); - try { - singleton().doCompile.invoke(compiler, taskHsHandle, compilableHsHandle, listenerHsHandle); - } finally { - Heap.getHeap().doReferenceHandling(); - Heap.getHeap().getGC().collectionHint(true); - } - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_shutdown") - @TruffleToLibGraal(Id.Shutdown) - public static void shutdown(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.Shutdown, env)) { - Object compiler = LibGraalObjectHandles.resolve(handle, Object.class); - singleton().shutdown.invoke(compiler); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_installTruffleCallBoundaryMethod") - @TruffleToLibGraal(Id.InstallTruffleCallBoundaryMethod) - public static void installTruffleCallBoundaryMethod(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, long methodHandle) { - try (JNIMethodScope s = openScope(Id.InstallTruffleCallBoundaryMethod, env)) { - Object compiler = LibGraalObjectHandles.resolve(handle, Object.class); - singleton().installTruffleCallBoundaryMethod.invoke(compiler, methodHandle); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_installTruffleReservedOopMethod") - @TruffleToLibGraal(Id.InstallTruffleReservedOopMethod) - public static void installTruffleReservedOopMethod(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, long methodHandle) { - try (JNIMethodScope s = openScope(Id.InstallTruffleReservedOopMethod, env)) { - Object compiler = LibGraalObjectHandles.resolve(handle, Object.class); - singleton().installTruffleReservedOopMethod.invoke(compiler, methodHandle); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @SuppressWarnings("unused") - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_pendingTransferToInterpreterOffset") - @TruffleToLibGraal(Id.PendingTransferToInterpreterOffset) - public static int pendingTransferToInterpreterOffset(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, JObject hsCompilable) { - try (JNIMethodScope scope = openScope(Id.PendingTransferToInterpreterOffset, env)) { - Object compiler = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().pendingTransferToInterpreterOffset.invoke(compiler, new HSObject(scope, hsCompilable)); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getSuppliedString") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetSuppliedString) - public static JString getSuppliedString(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try { - JNIMethodScope scope = openScope(Id.GetSuppliedString, env); - try (JNIMethodScope s = scope) { - Object stringSupplier = LibGraalObjectHandles.resolve(handle, Object.class); - if (stringSupplier != null) { - String stackTrace = (String) singleton().getSuppliedString.invoke(stringSupplier); - scope.setObjectResult(JNIUtil.createHSString(env, stackTrace)); - } else { - scope.setObjectResult(Word.nullPointer()); - } - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getNodeCount") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetNodeCount) - public static int getNodeCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetNodeCount, env)) { - Object graphInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getNodeCount.invoke(graphInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getNodeTypes") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetNodeTypes) - public static JObjectArray getNodeTypes(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle, boolean simpleNames) { - try { - JNIMethodScope scope = openScope(Id.GetNodeTypes, env); - try (JNIMethodScope s = scope) { - Object graphInfo = LibGraalObjectHandles.resolve(handle, Object.class); - String[] nodeTypes = (String[]) singleton().getNodeTypes.invoke(graphInfo, simpleNames); - JClass componentType = getStringClass(env); - JObjectArray res = JNIUtil.NewObjectArray(env, nodeTypes.length, componentType, Word.nullPointer()); - for (int i = 0; i < nodeTypes.length; i++) { - JNIUtil.SetObjectArrayElement(env, res, i, JNIUtil.createHSString(env, nodeTypes[i])); - } - scope.setObjectResult(res); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - private static JClass getStringClass(JNIEnv env) { - return JNIUtil.NewGlobalRef(env, JNIUtil.findClass(env, "java/lang/String"), "Class"); - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls2_getCompilationId") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetCompilationId) - public static long getCompilationId(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try { - JNIMethodScope scope = openScope(Id.GetCompilationId, env); - try (JNIMethodScope s = scope) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (long) singleton().getCompilationId.invoke(compilationResultInfo); - } - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return -1; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getTargetCodeSize") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetTargetCodeSize) - public static int getTargetCodeSize(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetTargetCodeSize, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getTargetCodeSize.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getTotalFrameSize") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetTotalFrameSize) - public static int getTotalFrameSize(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetTotalFrameSize, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getTotalFrameSize.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getExceptionHandlersCount") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetExceptionHandlersCount) - public static int getExceptionHandlersCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetExceptionHandlersCount, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getExceptionHandlersCount.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getInfopointsCount") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetInfopointsCount) - public static int getInfopointsCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetInfopointsCount, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getInfopointsCount.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getInfopoints") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetInfopoints) - public static JObjectArray getInfopoints(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try { - JNIMethodScope scope = openScope(Id.GetInfopoints, env); - try (JNIMethodScope s = scope) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - String[] infoPoints = (String[]) singleton().getInfopoints.invoke(compilationResultInfo); - JClass componentType = getStringClass(env); - JObjectArray res = JNIUtil.NewObjectArray(env, infoPoints.length, componentType, Word.nullPointer()); - for (int i = 0; i < infoPoints.length; i++) { - JNIUtil.SetObjectArrayElement(env, res, i, JNIUtil.createHSString(env, infoPoints[i])); - } - scope.setObjectResult(res); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getMarksCount") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetMarksCount) - public static int getMarksCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetMarksCount, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getMarksCount.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getDataPatchesCount") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetDataPatchesCount) - public static int getDataPatchesCount(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, long handle) { - try (JNIMethodScope s = openScope(Id.GetDataPatchesCount, env)) { - Object compilationResultInfo = LibGraalObjectHandles.resolve(handle, Object.class); - return (int) singleton().getDataPatchesCount.invoke(compilationResultInfo); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return 0; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_listCompilerOptions") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.ListCompilerOptions) - public static JByteArray listCompilerOptions(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress) { - try { - JNIMethodScope scope = openScope(Id.ListCompilerOptions, env); - try (JNIMethodScope s = scope) { - Object[] options = (Object[]) singleton().listCompilerOptions.invoke(); - BinaryOutput.ByteArrayBinaryOutput out = BinaryOutput.create(); - out.writeInt(options.length); - for (int i = 0; i < options.length; i++) { - TruffleCompilerOptionDescriptor descriptor = (TruffleCompilerOptionDescriptor) options[i]; - out.writeUTF(descriptor.name()); - out.writeInt(descriptor.type().ordinal()); - out.writeBoolean(descriptor.deprecated()); - out.writeUTF(descriptor.help()); - out.writeUTF(descriptor.deprecationMessage()); - } - JByteArray res = JNIUtil.createHSArray(env, out.getArray()); - scope.setObjectResult(res); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_compilerOptionExists") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.CompilerOptionExists) - public static boolean compilerOptionExists(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JString optionName) { - try (JNIMethodScope scope = openScope(Id.CompilerOptionExists, env)) { - return (boolean) singleton().compilerOptionExists.invoke(JNIUtil.createString(env, optionName)); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return false; - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_validateCompilerOption") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.ValidateCompilerOption) - public static JString validateCompilerOption(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JString optionName, JString optionValue) { - try { - JNIMethodScope scope = openScope(Id.ValidateCompilerOption, env); - try (JNIMethodScope s = scope) { - String result = (String) singleton().validateCompilerOption.invoke(JNIUtil.createString(env, optionName), JNIUtil.createString(env, optionValue)); - scope.setObjectResult(JNIUtil.createHSString(env, result)); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_purgePartialEvaluationCaches") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.PurgePartialEvaluationCaches) - public static void purgePartialEvaluationCaches(JNIEnv env, JClass hsClass, @IsolateThreadContext long isolateThreadAddress, long compilerHandle) { - try (JNIMethodScope s = openScope(Id.PurgePartialEvaluationCaches, env)) { - Object compiler = LibGraalObjectHandles.resolve(compilerHandle, Object.class); - if (compiler != null) { - singleton().purgePartialEvaluationCaches.invoke(compiler); - } - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_getCompilerVersion") - @SuppressWarnings({"unused", "try"}) - @TruffleToLibGraal(Id.GetCompilerVersion) - public static JString getCompilerVersion(JNIEnv env, JClass hsClass, @IsolateThreadContext long isolateThreadAddress) { - try { - JNIMethodScope scope = openScope(Id.GetCompilerVersion, env); - try (JNIMethodScope s = scope) { - String version = (String) singleton().getCompilerVersion.invoke(); - scope.setObjectResult(JNIUtil.createHSString(env, version)); - } - return scope.getObjectResult(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(env, t); - return Word.nullPointer(); - } - } - - @CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_LibGraalObject_releaseHandle") - @SuppressWarnings("unused") - public static boolean releaseHandle(JNIEnv jniEnv, JClass jclass, @IsolateThreadContext long isolateThreadAddress, long handle) { - try { - ObjectHandles.getGlobal().destroy(Word.pointer(handle)); - return true; - } catch (Throwable t) { - return false; - } - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java deleted file mode 100644 index 6e80301d3a26..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import static java.lang.invoke.MethodType.methodType; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.invoke.MethodType; -import java.lang.reflect.Modifier; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.regex.Pattern; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.jniutils.NativeBridgeSupport; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; -import org.graalvm.nativeimage.hosted.RuntimeReflection; - -import com.oracle.graal.pointsto.BigBang; -import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.graal.pointsto.reports.CallTreePrinter; -import com.oracle.svm.core.SubstrateTargetDescription; -import com.oracle.svm.core.hub.ClassForNameSupport; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.graal.hotspot.GetCompilerConfig; -import com.oracle.svm.graal.hotspot.GetJNIConfig; -import com.oracle.svm.hosted.FeatureImpl.AfterAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; -import com.oracle.svm.util.ModuleSupport; -import com.oracle.svm.util.ModuleSupport.Access; -import com.oracle.svm.util.ReflectionUtil; - -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; -import jdk.graal.compiler.hotspot.libgraal.BuildTime; -import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase; -import jdk.graal.compiler.options.OptionDescriptor; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.serviceprovider.LibGraalService; -import jdk.vm.ci.code.TargetDescription; - -/** - * This feature builds the libgraal shared library (e.g., libjvmcicompiler.so on linux). - *

- * With use of {@code -Djdk.graal.internal.libgraal.javahome=path}, the Graal and JVMCI classes from - * which libgraal is built can be from a "guest" JDK that may be different from the JDK on which - * Native Image is running. - *

- * This feature is composed of these key classes: - *

    - *
  • {@code HostedLibGraalClassLoader}
  • - *
  • {@link LibGraalEntryPoints}
  • - *
  • {@link LibGraalSubstitutions}
  • - *
- */ -@Platforms(Platform.HOSTED_ONLY.class) -public final class LibGraalFeature implements Feature { - - public static final class IsEnabled implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return ImageSingletons.contains(LibGraalFeature.class); - } - } - - @Override - public List> getRequiredFeatures() { - return List.of(LibGraalFieldsOffsetsFeature.class); - } - - final MethodHandles.Lookup mhl = MethodHandles.lookup(); - - LibGraalClassLoaderBase libGraalClassLoader; - - /** - * Loader used for loading classes from the guest GraalVM. - */ - ClassLoader loader; - - /** - * Handle to {@link BuildTime} in the guest. - */ - Class buildTimeClass; - - /** - * Handle to {@link jdk.graal.compiler.phases.BasePhase} in the guest. - */ - private Class basePhaseClass; - - private Function, Object> newBasePhaseStatistics; - - /** - * Handle to {@link jdk.graal.compiler.lir.phases.LIRPhase} in the guest. - */ - private Class lirPhaseClass; - - private Function, Object> newLIRPhaseStatistics; - - MethodHandle handleGlobalAtomicLongGetInitialValue; - - public ClassLoader getLoader() { - return loader; - } - - public Class loadClassOrFail(Class c) { - if (c.getClassLoader() == loader) { - return c; - } - if (c.isArray()) { - return loadClassOrFail(c.getComponentType()).arrayType(); - } - return loadClassOrFail(c.getName()); - } - - public Class loadClassOrFail(String name) { - try { - return loader.loadClass(name); - } catch (ClassNotFoundException e) { - throw new AssertionError("%s unable to load class '%s'".formatted(loader.getName(), name)); - } - } - - /** - * Performs tasks once this feature is registered. - *
    - *
  • Create the {@code HostedLibGraalClassLoader} instance.
  • - *
  • Get a handle to the {@link BuildTime} class in the guest.
  • - *
  • Initializes the options in the guest.
  • - *
  • Initializes some state needed by {@link LibGraalSubstitutions}.
  • - *
- */ - @Override - public void afterRegistration(AfterRegistrationAccess access) { - // LibGraalEntryPoints uses a number of classes in org.graalvm.nativeimage.builder - accessModulesToClass(ModuleSupport.Access.EXPORT, LibGraalFeature.class, - "org.graalvm.nativeimage.builder"); - - // LibGraalFeature accesses a few Graal classes (see import statements above) - accessModulesToClass(ModuleSupport.Access.EXPORT, LibGraalFeature.class, "jdk.graal.compiler"); - - // LibGraalTruffleToLibGraalEntryPoints access TruffleToLibGraal.Id - accessModulesToClass(ModuleSupport.Access.EXPORT, LibGraalFeature.class, "org.graalvm.truffle.compiler"); - - ImageSingletons.add(NativeBridgeSupport.class, new LibGraalNativeBridgeSupport()); - // Target_jdk_graal_compiler_serviceprovider_VMSupport.getIsolateID needs access to - // org.graalvm.nativeimage.impl.IsolateSupport - accessModulesToClass(ModuleSupport.Access.EXPORT, LibGraalFeature.class, "org.graalvm.nativeimage"); - - libGraalClassLoader = createHostedLibGraalClassLoader(access); - loader = libGraalClassLoader.getClassLoader(); - ClassForNameSupport.currentLayer().setLibGraalLoader(loader); - - buildTimeClass = loadClassOrFail("jdk.graal.compiler.hotspot.libgraal.BuildTime"); - - // Guest JVMCI and Graal need access to some JDK internal packages - String[] basePackages = {"jdk.internal.misc", "jdk.internal.util", "jdk.internal.vm"}; - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, null, false, "java.base", basePackages); - - try { - /* - * Get GlobalAtomicLong.getInitialValue() method from LibGraalClassLoader for - * LibGraalGraalSubstitutions.GlobalAtomicLongAddressProvider FieldValueTransformer - */ - handleGlobalAtomicLongGetInitialValue = mhl.findVirtual(loadClassOrFail("jdk.graal.compiler.serviceprovider.GlobalAtomicLong"), - "getInitialValue", methodType(long.class)); - - } catch (Throwable e) { - VMError.shouldNotReachHere(e); - } - } - - @SuppressWarnings("unchecked") - private static LibGraalClassLoaderBase createHostedLibGraalClassLoader(AfterRegistrationAccess access) { - var hostedLibGraalClassLoaderClass = access.findClassByName("jdk.graal.compiler.hotspot.libgraal.HostedLibGraalClassLoader"); - ModuleSupport.accessPackagesToClass(Access.EXPORT, hostedLibGraalClassLoaderClass, false, "java.base", "jdk.internal.module"); - return ReflectionUtil.newInstance((Class) hostedLibGraalClassLoaderClass); - } - - private static void accessModulesToClass(ModuleSupport.Access access, Class accessingClass, String... moduleNames) { - for (String moduleName : moduleNames) { - var module = getBootModule(moduleName); - ModuleSupport.accessPackagesToClass(access, accessingClass, false, - module.getName(), module.getPackages().toArray(String[]::new)); - } - } - - static Module getBootModule(String moduleName) { - return ModuleLayer.boot().findModule(moduleName).orElseThrow(); - } - - @Override - public void duringSetup(DuringSetupAccess access) { - - /* - * HostedLibGraalClassLoader provides runtime-replacement loader instance. Make sure - * HostedLibGraalClassLoader gets replaced by customRuntimeLoader instance in image. - */ - ClassLoader customRuntimeLoader = libGraalClassLoader.getRuntimeClassLoader(); - access.registerObjectReplacer(obj -> obj == loader ? customRuntimeLoader : obj); - - try { - var basePhaseStatisticsClass = loadClassOrFail("jdk.graal.compiler.phases.BasePhase$BasePhaseStatistics"); - var lirPhaseStatisticsClass = loadClassOrFail("jdk.graal.compiler.lir.phases.LIRPhase$LIRPhaseStatistics"); - MethodType statisticsCTorType = methodType(void.class, Class.class); - var basePhaseStatisticsCTor = mhl.findConstructor(basePhaseStatisticsClass, statisticsCTorType); - var lirPhaseStatisticsCTor = mhl.findConstructor(lirPhaseStatisticsClass, statisticsCTorType); - newBasePhaseStatistics = new StatisticsCreator(basePhaseStatisticsCTor)::create; - newLIRPhaseStatistics = new StatisticsCreator(lirPhaseStatisticsCTor)::create; - - basePhaseClass = loadClassOrFail("jdk.graal.compiler.phases.BasePhase"); - lirPhaseClass = loadClassOrFail("jdk.graal.compiler.lir.phases.LIRPhase"); - - ImageSingletons.add(LibGraalCompilerSupport.class, new LibGraalCompilerSupport()); - } catch (Throwable e) { - throw VMError.shouldNotReachHere("Failed to invoke jdk.graal.compiler.hotspot.libgraal.BuildTime methods", e); - } - - DuringSetupAccessImpl accessImpl = (DuringSetupAccessImpl) access; - accessImpl.registerClassReachabilityListener(this::registerPhaseStatistics); - optionCollector = new OptionCollector(LibGraalEntryPoints.vmOptionDescriptors); - access.registerObjectReachabilityHandler(optionCollector::accept, OptionKey.class); - access.registerObjectReachabilityHandler(optionCollector::accept, loadClassOrFail(OptionKey.class.getName())); - GetJNIConfig.register(loader); - } - - private OptionCollector optionCollector; - - /** - * Collects all options that are reachable at run time. Reachable options are the - * {@link OptionKey} instances reached by the static analysis. The VM options are instances of - * {@link OptionKey} loaded by the {@link com.oracle.svm.hosted.NativeImageClassLoader} and - * compiler options are instances of {@link OptionKey} loaded by the - * {@code HostedLibGraalClassLoader}. - */ - private class OptionCollector implements Consumer { - private final Set options = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - /** - * Libgraal VM options. - */ - private final EconomicMap vmOptionDescriptors; - - /** - * Libgraal compiler options info. - */ - private final Object compilerOptionsInfo; - - private boolean sealed; - - OptionCollector(EconomicMap vmOptionDescriptors) { - this.vmOptionDescriptors = vmOptionDescriptors; - try { - MethodType mt = methodType(Object.class); - MethodHandle mh = mhl.findStatic(buildTimeClass, "initLibgraalOptions", mt); - compilerOptionsInfo = mh.invoke(); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - @Override - public void accept(Object option) { - if (sealed) { - VMError.guarantee(options.contains(option), "All options must have been discovered during static analysis: %s", option); - } else { - options.add(option); - } - } - - @SuppressWarnings("unchecked") - void afterAnalysis(AfterAnalysisAccess access) { - sealed = true; - List compilerOptions = new ArrayList<>(options.size()); - for (Object option : options) { - if (option instanceof OptionKey optionKey) { - OptionDescriptor descriptor = optionKey.getDescriptor(); - if (descriptor.isServiceLoaded()) { - VMError.guarantee(access.isReachable(option.getClass()), "%s", option.getClass()); - VMError.guarantee(access.isReachable(descriptor.getClass()), "%s", descriptor.getClass()); - vmOptionDescriptors.put(optionKey.getName(), descriptor); - } - } else { - ClassLoader optionCL = option.getClass().getClassLoader(); - VMError.guarantee(optionCL == loader, "unexpected option loader: %s", optionCL); - compilerOptions.add(option); - } - } - try { - MethodType mt = methodType(Iterable.class, List.class, Object.class, Map.class); - MethodHandle mh = mhl.findStatic(buildTimeClass, "finalizeLibgraalOptions", mt); - Map modules = ReflectionUtil.invokeMethod(ReflectionUtil.lookupMethod(loader.getClass(), "getModules"), loader); - Iterable values = (Iterable) mh.invoke(compilerOptions, compilerOptionsInfo, modules); - for (Object descriptor : values) { - VMError.guarantee(access.isReachable(descriptor.getClass()), "%s", descriptor.getClass()); - } - } catch (Throwable e) { - VMError.shouldNotReachHere(e); - } - } - } - - private record StatisticsCreator(MethodHandle ctorHandle) { - Object create(Class clazz) { - try { - return ctorHandle.invoke(clazz); - } catch (Throwable e) { - throw VMError.shouldNotReachHere("Failed to create new instance of Statistics clazz with MethodHandle " + ctorHandle, e); - } - } - } - - private void registerPhaseStatistics(DuringAnalysisAccess a, Class newlyReachableClass) { - DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a; - - if (!Modifier.isAbstract(newlyReachableClass.getModifiers())) { - boolean requireAnalysisIteration = true; - if (basePhaseClass.isAssignableFrom(newlyReachableClass)) { - LibGraalCompilerSupport.registerStatistics(newlyReachableClass, LibGraalCompilerSupport.get().basePhaseStatistics, - newBasePhaseStatistics.apply(newlyReachableClass)); - - } else if (lirPhaseClass.isAssignableFrom(newlyReachableClass)) { - LibGraalCompilerSupport.registerStatistics(newlyReachableClass, LibGraalCompilerSupport.get().lirPhaseStatistics, - newLIRPhaseStatistics.apply(newlyReachableClass)); - } else { - requireAnalysisIteration = false; - } - - if (requireAnalysisIteration) { - access.requireAnalysisIteration(); - } - } - } - - @Override - public void beforeAnalysis(BeforeAnalysisAccess baa) { - BeforeAnalysisAccessImpl impl = (BeforeAnalysisAccessImpl) baa; - var bb = impl.getBigBang(); - - /* Contains static fields that depend on HotSpotJVMCIRuntime */ - RuntimeClassInitialization.initializeAtRunTime(loadClassOrFail("jdk.vm.ci.hotspot.HotSpotModifiers")); - RuntimeClassInitialization.initializeAtRunTime(loadClassOrFail("jdk.vm.ci.hotspot.HotSpotCompiledCodeStream")); - RuntimeClassInitialization.initializeAtRunTime(loadClassOrFail("jdk.vm.ci.hotspot.HotSpotCompiledCodeStream$Tag")); - /* ThreadLocal in static field jdk.graal.compiler.debug.DebugContext.activated */ - RuntimeClassInitialization.initializeAtRunTime(loadClassOrFail("jdk.graal.compiler.debug.DebugContext")); - - /* Needed for runtime calls to BoxingSnippets.Templates.getCacheClass(JavaKind) */ - RuntimeReflection.registerAllDeclaredClasses(Character.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Character$CharacterCache"), "cache")); - RuntimeReflection.registerAllDeclaredClasses(Byte.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Byte$ByteCache"), "cache")); - RuntimeReflection.registerAllDeclaredClasses(Short.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Short$ShortCache"), "cache")); - RuntimeReflection.registerAllDeclaredClasses(Integer.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Integer$IntegerCache"), "cache")); - RuntimeReflection.registerAllDeclaredClasses(Long.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Long$LongCache"), "cache")); - - /* Configure static state of Graal. */ - try { - TargetDescription targetDescription = ImageSingletons.lookup(SubstrateTargetDescription.class); - String arch = targetDescription.arch.getName(); - - Consumer> registerAsInHeap = nodeClass -> impl.getMetaAccess().lookupJavaType(nodeClass) - .registerAsInstantiated("All NodeClass classes are marked as instantiated eagerly."); - - List> guestServiceClasses = new ArrayList<>(); - List> serviceClasses = impl.getImageClassLoader().findAnnotatedClasses(LibGraalService.class, false); - serviceClasses.stream().map(c -> loadClassOrFail(c.getName())).forEach(guestServiceClasses::add); - - // Transfer libgraal qualifier (e.g. "PGO optimized") from host to guest. - String nativeImageLocationQualifier = CompilerConfigurationFactory.getNativeImageLocationQualifier(); - - MethodHandle configureGraalForLibGraal = mhl.findStatic(buildTimeClass, - "configureGraalForLibGraal", - methodType(void.class, - String.class, // arch - List.class, // guestServiceClasses - Consumer.class, // registerAsInHeap - String.class, // nativeImageLocationQualifier - byte[].class // encodedGuestObjects - )); - Path libGraalJavaHome = ReflectionUtil.readField(loader.getClass(), "libGraalJavaHome", loader); - GetCompilerConfig.Result configResult = GetCompilerConfig.from(libGraalJavaHome, bb.getOptions()); - for (var e : configResult.opens().entrySet()) { - for (String source : e.getValue()) { - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, buildTimeClass, false, e.getKey(), source); - } - } - - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, buildTimeClass, false, "org.graalvm.word", "org.graalvm.word.impl"); - - configureGraalForLibGraal.invoke(arch, - guestServiceClasses, - registerAsInHeap, - nativeImageLocationQualifier, - configResult.encodedConfig()); - - initGraalRuntimeHandles(mhl.findStatic(buildTimeClass, "getRuntimeHandles", methodType(Map.class))); - initializeTruffle(); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - @SuppressWarnings("unchecked") - private static void initGraalRuntimeHandles(MethodHandle getRuntimeHandles) throws Throwable { - ImageSingletons.add(LibGraalEntryPoints.class, new LibGraalEntryPoints((Map) getRuntimeHandles.invoke())); - } - - @SuppressWarnings("unchecked") - private void initializeTruffle() throws Throwable { - Class truffleBuildTimeClass = loadClassOrFail("jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime"); - MethodHandle getLookup = mhl.findStatic(truffleBuildTimeClass, "initializeLookup", methodType(Map.Entry.class, Lookup.class, Class.class, Class.class)); - Map.Entry> truffleLibGraal = (Map.Entry>) getLookup.invoke(mhl, TruffleFromLibGraalStartPoints.class, NativeImageHostEntryPoints.class); - ImageSingletons.add(LibGraalTruffleToLibGraalEntryPoints.class, new LibGraalTruffleToLibGraalEntryPoints(truffleLibGraal.getKey(), truffleLibGraal.getValue())); - MethodHandle truffleConfigureGraalForLibGraal = mhl.findStatic(truffleBuildTimeClass, "configureGraalForLibGraal", methodType(void.class)); - truffleConfigureGraalForLibGraal.invoke(); - } - - @SuppressWarnings("try") - @Override - public void afterAnalysis(AfterAnalysisAccess access) { - /* - * Verify we only have JVMCI & Graal classes reachable that are coming from - * LibGraalClassLoader except for hosted JVMCI & Graal classes that are legitimately used by - * SubstrateVM runtime implementation classes (mostly from package com.oracle.svm.core). - */ - List hostedAllowed = List.of( - classesPattern("jdk.graal.compiler.core.common", - "NumUtil"), - classesPattern("jdk.graal.compiler.core.common.util", - "AbstractTypeReader", "TypeConversion", "TypeReader", "UnsafeArrayTypeReader"), - classesPattern("jdk.graal.compiler.core.common.type", - "CompressibleConstant"), - classesPattern("jdk.graal.compiler.debug", - "GraalError"), - classesPattern("jdk.graal.compiler.options", - "ModifiableOptionValues", "Option.*"), - classesPattern("jdk.graal.compiler.util.json", - "JsonWriter", "JsonBuilder.*"), - classesPattern("org.graalvm.collections", - "EconomicMap.*", "EmptyMap.*", "Equivalence.*", "Pair"), - classesPattern("jdk.vm.ci.amd64", - "AMD64.*"), - classesPattern("jdk.vm.ci.aarch64", - "AArch64.*"), - classesPattern("jdk.vm.ci.riscv64", - "RISCV64.*"), - classesPattern("jdk.vm.ci.code", - "Architecture", "Register.*", "TargetDescription"), - classesPattern("jdk.vm.ci.meta", - "JavaConstant", "JavaKind", "MetaUtil", "NullConstant", "PrimitiveConstant")); - - Set forbiddenHostedModules = Set.of("jdk.internal.vm.ci", "org.graalvm.collections", "org.graalvm.word", "jdk.graal.compiler"); - - AfterAnalysisAccessImpl accessImpl = (AfterAnalysisAccessImpl) access; - BigBang bigBang = accessImpl.getBigBang(); - CallTreePrinter callTreePrinter = new CallTreePrinter(bigBang); - callTreePrinter.buildCallTree(); - - DebugContext debug = bigBang.getDebug(); - List forbiddenReachableTypes = new ArrayList<>(); - try (DebugContext.Scope ignored = debug.scope("LibGraalEntryPoints")) { - for (AnalysisType analysisType : callTreePrinter.usedAnalysisTypes()) { - Class reachableType = analysisType.getJavaClass(); - if (reachableType.getClassLoader() == loader || reachableType.isArray()) { - continue; - } - Module module = reachableType.getModule(); - if (module.isNamed() && forbiddenHostedModules.contains(module.getName())) { - String fqn = reachableType.getName(); - if (hostedAllowed.stream().anyMatch(pattern -> pattern.matcher(fqn).matches())) { - debug.log("Allowing hosted class %s from %s", fqn, module); - continue; - } - forbiddenReachableTypes.add(String.format("%s/%s", module.getName(), fqn)); - } - } - } - if (!forbiddenReachableTypes.isEmpty()) { - CallTreePrinter.print(bigBang, "reports", "report"); - VMError.shouldNotReachHere("LibGraalEntryPoints build found forbidden hosted types as reachable: %s", String.join(", ", forbiddenReachableTypes)); - } - optionCollector.afterAnalysis(access); - } - - private static Pattern classesPattern(String packageName, String... regexes) { - return Pattern.compile("%s(%s)".formatted(Pattern.quote(packageName + '.'), String.join("|", regexes))); - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFieldsOffsetsFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFieldsOffsetsFeature.java deleted file mode 100644 index a5474369f3e0..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFieldsOffsetsFeature.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.Function; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.nativeimage.ImageSingletons; - -import com.oracle.graal.pointsto.meta.AnalysisField; -import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.svm.core.BuildPhaseProvider; -import com.oracle.svm.core.feature.InternalFeature; -import com.oracle.svm.core.fieldvaluetransformer.FieldValueTransformerWithAvailability; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.CompilationAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; -import com.oracle.svm.hosted.meta.HostedMetaAccess; -import com.oracle.svm.util.ModuleSupport; -import com.oracle.svm.util.ReflectionUtil; - -import jdk.internal.misc.Unsafe; - -/** - * Graal uses unsafe memory accesses to access {@code Node}s and {@code LIRInstruction}s. The - * offsets for these accesses are maintained in {@code Fields}, which are accessible from - * meta-classes such as {@code NodeClass} and {@code LIRInstructionClass}. We do not want to replace - * the whole meta-classes. Instead, we just replace the {@code long[]} arrays that hold the actual - * offsets. - */ -public final class LibGraalFieldsOffsetsFeature implements InternalFeature { - - private final MethodHandles.Lookup mhl = MethodHandles.lookup(); - private LibGraalFeature libGraalFeature; - - private Class fieldsClass; - private Class edgesClass; - private Class edgesTypeClass; - private MethodHandle fieldsClassGetOffsetsMethod; - private MethodHandle fieldsClassGetCountMethod; - private MethodHandle fieldsClassGetDeclaringClassMethod; - private MethodHandle fieldsClassGetNameMethod; - - private MethodHandle edgesClassTypeMethod; - private MethodHandle edgesClassGetDirectCountMethod; - - private Class nodeClass; - private Class nodeClassClass; - private Class inputEdgesClass; - private Class successorEdgesClass; - private MethodHandle nodeClassClassGetMethod; - private MethodHandle nodeClassClassGetInputEdgesMethod; - private MethodHandle nodeClassClassGetSuccessorEdgesMethod; - private MethodHandle nodeClassClassGetShortNameMethod; - private MethodHandle nodeClassClassComputeIterationMaskMethod; - - private Class fieldIntrospectionClass; - private MethodHandle fieldIntrospectionClassGetDataMethod; - private MethodHandle fieldIntrospectionClassGetAllFieldsMethod; - private MethodHandle fieldIntrospectionClassGetClazzMethod; - private Class lirInstructionClass; - private Class lirInstructionClassClass; - private MethodHandle lirInstructionClassClassGetMethod; - - private static class FieldsOffsetsReplacement { - protected final Object fields; - protected boolean newValuesAvailable; - protected long[] newOffsets; - protected long newIterationInitMask; - - protected FieldsOffsetsReplacement(Object fields) { - this.fields = fields; - } - } - - static class FieldsOffsetsReplacements { - protected final Map replacements = new IdentityHashMap<>(); - protected boolean sealed; - } - - private static Map getReplacements() { - return ImageSingletons.lookup(FieldsOffsetsReplacements.class).replacements; - } - - @Override - public void duringSetup(DuringSetupAccess a) { - DuringSetupAccessImpl access = (DuringSetupAccessImpl) a; - libGraalFeature = ImageSingletons.lookup(LibGraalFeature.class); - - fieldsClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.core.common.Fields"); - edgesClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.Edges"); - edgesTypeClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.Edges$Type"); - nodeClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.Node"); - nodeClassClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.NodeClass"); - lirInstructionClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.lir.LIRInstruction"); - lirInstructionClassClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.lir.LIRInstructionClass"); - fieldIntrospectionClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.core.common.FieldIntrospection"); - inputEdgesClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.InputEdges"); - successorEdgesClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.graph.SuccessorEdges"); - - try { - fieldsClassGetOffsetsMethod = mhl.findVirtual(fieldsClass, "getOffsets", MethodType.methodType(long[].class)); - fieldsClassGetCountMethod = mhl.findVirtual(fieldsClass, "getCount", MethodType.methodType(int.class)); - fieldsClassGetDeclaringClassMethod = mhl.findVirtual(fieldsClass, "getDeclaringClass", MethodType.methodType(Class.class, int.class)); - fieldsClassGetNameMethod = mhl.findVirtual(fieldsClass, "getName", MethodType.methodType(String.class, int.class)); - - edgesClassTypeMethod = mhl.findVirtual(edgesClass, "type", MethodType.methodType(edgesTypeClass)); - edgesClassGetDirectCountMethod = mhl.findVirtual(edgesClass, "getDirectCount", MethodType.methodType(int.class)); - - nodeClassClassGetMethod = mhl.findStatic(nodeClassClass, "get", MethodType.methodType(nodeClassClass, Class.class)); - nodeClassClassGetInputEdgesMethod = mhl.findVirtual(nodeClassClass, "getInputEdges", MethodType.methodType(inputEdgesClass)); - nodeClassClassGetSuccessorEdgesMethod = mhl.findVirtual(nodeClassClass, "getSuccessorEdges", MethodType.methodType(successorEdgesClass)); - nodeClassClassGetShortNameMethod = mhl.findVirtual(nodeClassClass, "shortName", MethodType.methodType(String.class)); - nodeClassClassGetShortNameMethod = mhl.findVirtual(nodeClassClass, "shortName", MethodType.methodType(String.class)); - nodeClassClassComputeIterationMaskMethod = mhl.findStatic(nodeClassClass, "computeIterationMask", MethodType.methodType(long.class, edgesTypeClass, int.class, long[].class)); - - lirInstructionClassClassGetMethod = mhl.findStatic(lirInstructionClassClass, "get", MethodType.methodType(lirInstructionClassClass, Class.class)); - - fieldIntrospectionClassGetDataMethod = mhl.findVirtual(fieldIntrospectionClass, "getData", MethodType.methodType(fieldsClass)); - fieldIntrospectionClassGetAllFieldsMethod = mhl.findVirtual(fieldIntrospectionClass, "getAllFields", MethodType.methodType(fieldsClass.arrayType())); - fieldIntrospectionClassGetClazzMethod = mhl.findVirtual(fieldIntrospectionClass, "getClazz", MethodType.methodType(Class.class)); - - } catch (ReflectiveOperationException e) { - throw VMError.shouldNotReachHere(e); - } - - ModuleSupport.accessModuleByClass(ModuleSupport.Access.EXPORT, LibGraalFieldsOffsetsFeature.class, InternalFeature.class); - ImageSingletons.add(FieldsOffsetsReplacements.class, new FieldsOffsetsReplacements()); - access.registerObjectReplacer(this::replaceFieldsOffsets); - access.registerClassReachabilityListener(this::classReachabilityListener); - } - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - MethodHandle getInputEdgesOffsets; - MethodHandle getSuccessorEdgesOffsets; - var buildTimeClass = libGraalFeature.loadClassOrFail("jdk.graal.compiler.hotspot.libgraal.BuildTime"); - try { - MethodType offsetAccessorSignature = MethodType.methodType(long[].class, Object.class); - getInputEdgesOffsets = mhl.findStatic(buildTimeClass, "getInputEdgesOffsets", offsetAccessorSignature); - getSuccessorEdgesOffsets = mhl.findStatic(buildTimeClass, "getSuccessorEdgesOffsets", offsetAccessorSignature); - } catch (ReflectiveOperationException e) { - throw VMError.shouldNotReachHere(e); - } - - access.registerFieldValueTransformer(ReflectionUtil.lookupField(nodeClassClass, "inputsIteration"), - new IterationMaskRecomputation(getInputEdgesOffsets)); - access.registerFieldValueTransformer(ReflectionUtil.lookupField(nodeClassClass, "successorIteration"), - new IterationMaskRecomputation(getSuccessorEdgesOffsets)); - } - - private static class IterationMaskRecomputation implements FieldValueTransformerWithAvailability { - - private final MethodHandle offsetsFromReceiver; - - IterationMaskRecomputation(MethodHandle offsetsFromReceiver) { - this.offsetsFromReceiver = offsetsFromReceiver; - } - - @Override - public boolean isAvailable() { - return BuildPhaseProvider.isHostedUniverseBuilt(); - } - - @Override - public Object transform(Object receiver, Object originalValue) { - FieldsOffsetsReplacement replacement; - try { - long[] offsetsFromEdges = (long[]) offsetsFromReceiver.invoke(receiver); - replacement = LibGraalFieldsOffsetsFeature.getReplacements().get(offsetsFromEdges); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - assert replacement.newValuesAvailable : "Cannot access iteration mask before field offsets are assigned"; - return replacement.newIterationInitMask; - } - } - - private Object replaceFieldsOffsets(Object source) { - if (fieldsClass.isInstance(source)) { - /* - * All instances of Fields must have been registered before, otherwise we miss the - * substitution of its offsets array. - */ - assert !ImageSingletons.lookup(FieldsOffsetsReplacements.class).sealed || getReplacements().containsKey(getOffsetsFromFields(source)) : source; - - } else if (source instanceof long[]) { - FieldsOffsetsReplacement replacement = getReplacements().get(source); - if (replacement != null) { - assert source == getOffsetsFromFields(replacement.fields); - - /* - * We can only compute the new offsets after static analysis, i.e., after the object - * layout is done and run-time field offsets are available. Until then, we return - * the hosted offsets so that we have a return value. The actual offsets do not - * matter at this point. - */ - if (replacement.newValuesAvailable) { - return replacement.newOffsets; - } - } - } - return source; - } - - /* Invoked once for every class that is reachable in the native image. */ - private void classReachabilityListener(DuringAnalysisAccess a, Class newlyReachableClass) { - DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a; - if (BuildPhaseProvider.isAnalysisFinished()) { - throw VMError.shouldNotReachHere("New class reachable after analysis: " + newlyReachableClass); - } - - if (!newlyReachableClass.equals(nodeClass) && nodeClass.isAssignableFrom(newlyReachableClass)) { - registerClass(newlyReachableClass, LibGraalCompilerSupport.get().nodeClasses, this::getNodeClassFromNode, false, access); - } else if (!newlyReachableClass.equals(lirInstructionClass) && lirInstructionClass.isAssignableFrom(newlyReachableClass)) { - registerClass(newlyReachableClass, LibGraalCompilerSupport.get().instructionClasses, this::getLIRInstructionClassFromLIRInstruction, true, access); - } - } - - private void registerClass(Class clazz, EconomicMap, Object> registry, - Function, Object> lookup, boolean excludeAbstract, DuringAnalysisAccessImpl access) { - assert !registry.containsKey(clazz); - - if (!excludeAbstract || !Modifier.isAbstract(clazz.getModifiers())) { - Object nodeClazz = lookup.apply(clazz); - registry.put(clazz, nodeClazz); - registerFields(nodeClazz, access); - - access.requireAnalysisIteration(); - } - } - - private void registerFields(Object introspection, BeforeAnalysisAccessImpl config) { - if (nodeClassClass.isInstance(introspection)) { - - /* The partial evaluator allocates Node classes via Unsafe. */ - AnalysisType nodeType = config.getMetaAccess().lookupJavaType(getClazzFromFieldIntrospection(introspection)); - nodeType.registerInstantiatedCallback(unused -> nodeType.registerAsUnsafeAllocated("Graal node class")); - - Object dataFields = getDataFromFieldIntrospection(introspection); - registerFields(dataFields, config, "Graal node data field"); - - Object inputEdges = getInputEdgesFromNodeClass(introspection); - registerFields(inputEdges, config, "Graal node input edge"); - - Object successorEdges = getSuccessorEdgesFromNodeClass(introspection); - registerFields(successorEdges, config, "Graal node successor edge"); - - /* Ensure field shortName is initialized, so that the instance is immutable. */ - invokeShortName(introspection); - - } else { - assert fieldIntrospectionClass.isInstance(introspection); - for (Object fields : getAllFieldsFromFieldIntrospection(introspection)) { - registerFields(fields, config, "Graal field"); - } - } - } - - private void registerFields(Object fields, BeforeAnalysisAccessImpl config, Object reason) { - getReplacements().put(getOffsetsFromFields(fields), new FieldsOffsetsReplacement(fields)); - - for (int i = 0; i < getCountFromFields(fields); i++) { - AnalysisField aField = config.getMetaAccess().lookupJavaField(findField(fields, i)); - aField.getType().registerAsReachable(aField); - config.registerAsUnsafeAccessed(aField, reason); - } - } - - private Field findField(Object fields, int index) { - try { - return getDeclaringClassFromFields(fields, index).getDeclaredField(getNameFromFields(fields, index)); - } catch (NoSuchFieldException ex) { - throw VMError.shouldNotReachHere(ex); - } - } - - @Override - public void beforeCompilation(BeforeCompilationAccess a) { - CompilationAccessImpl config = (CompilationAccessImpl) a; - HostedMetaAccess hMetaAccess = config.getMetaAccess(); - - getReplacements().forEach((originalOffsets, replacement) -> { - Object fields = replacement.fields; - long[] newOffsets = new long[getCountFromFields(fields)]; - for (int i = 0; i < newOffsets.length; i++) { - Field field = findField(fields, i); - assert Unsafe.getUnsafe().objectFieldOffset(field) == originalOffsets[i]; - newOffsets[i] = hMetaAccess.lookupJavaField(field).getLocation(); - } - replacement.newOffsets = newOffsets; - - if (edgesClass.isInstance(fields)) { - Object edges = edgesClass.cast(fields); - replacement.newIterationInitMask = nodeClassComputeIterationMask(typeFromEdges(edges), getDirectCountFromEdges(edges), newOffsets); - } - - replacement.newValuesAvailable = true; - }); - - ImageSingletons.lookup(FieldsOffsetsReplacements.class).sealed = true; - } - - @Override - public void afterCompilation(AfterCompilationAccess access) { - access.registerAsImmutable(LibGraalCompilerSupport.get().nodeClasses.getValues(), o -> true); - access.registerAsImmutable(LibGraalCompilerSupport.get().instructionClasses.getValues(), o -> true); - } - - private long[] getOffsetsFromFields(Object fields) { - try { - return (long[]) fieldsClassGetOffsetsMethod.invoke(fields); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private int getCountFromFields(Object fields) { - try { - return (int) fieldsClassGetCountMethod.invoke(fields); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Class getDeclaringClassFromFields(Object fields, int index) { - try { - return (Class) fieldsClassGetDeclaringClassMethod.invoke(fields, index); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private String getNameFromFields(Object fields, int index) { - try { - return (String) fieldsClassGetNameMethod.invoke(fields, index); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object typeFromEdges(Object edges) { - try { - assert edgesClass.isInstance(edges); - Object edgesType = edgesClassTypeMethod.invoke(edges); - return edgesTypeClass.cast(edgesType); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private int getDirectCountFromEdges(Object edges) { - try { - assert edgesClass.isInstance(edges); - return (int) edgesClassGetDirectCountMethod.invoke(edges); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object getDataFromFieldIntrospection(Object fieldIntrospection) { - try { - assert fieldIntrospectionClass.isInstance(fieldIntrospection); - Object fields = fieldIntrospectionClassGetDataMethod.invoke(fieldIntrospection); - return fieldsClass.cast(fields); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Class getClazzFromFieldIntrospection(Object fieldIntrospection) { - try { - assert fieldIntrospectionClass.isInstance(fieldIntrospection); - Object clazz = fieldIntrospectionClassGetClazzMethod.invoke(fieldIntrospection); - return (Class) clazz; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object[] getAllFieldsFromFieldIntrospection(Object fieldIntrospection) { - try { - assert fieldIntrospectionClass.isInstance(fieldIntrospection); - Object allFields = fieldIntrospectionClassGetAllFieldsMethod.invoke(fieldIntrospection); - return (Object[]) fieldsClass.arrayType().cast(allFields); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object getNodeClassFromNode(Class clazz) { - try { - assert nodeClass.isAssignableFrom(clazz); - Object nodeClassInstance = nodeClassClassGetMethod.invoke(clazz); - assert nodeClassClass.isInstance(nodeClassInstance); - return nodeClassInstance; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object getInputEdgesFromNodeClass(Object nodeClazz) { - try { - assert nodeClassClass.isInstance(nodeClazz); - Object inputEdges = nodeClassClassGetInputEdgesMethod.invoke(nodeClazz); - return inputEdgesClass.cast(inputEdges); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object getSuccessorEdgesFromNodeClass(Object nodeClazz) { - try { - assert nodeClassClass.isInstance(nodeClazz); - Object successorEdges = nodeClassClassGetSuccessorEdgesMethod.invoke(nodeClazz); - return successorEdgesClass.cast(successorEdges); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private void invokeShortName(Object nodeClazz) { - try { - assert nodeClassClass.isInstance(nodeClazz); - nodeClassClassGetShortNameMethod.invoke(nodeClazz); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private long nodeClassComputeIterationMask(Object edgesType, int directCount, long[] offsets) { - try { - assert edgesTypeClass.isInstance(edgesType); - return (long) nodeClassClassComputeIterationMaskMethod.invoke(edgesType, directCount, offsets); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } - - private Object getLIRInstructionClassFromLIRInstruction(Class clazz) { - try { - assert lirInstructionClass.isAssignableFrom(clazz); - Object nodeClassInstance = lirInstructionClassClassGetMethod.invoke(clazz); - assert lirInstructionClassClass.isInstance(nodeClassInstance); - return nodeClassInstance; - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalSubstitutions.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalSubstitutions.java deleted file mode 100644 index 14b29ffd7afd..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalSubstitutions.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import java.io.PrintStream; -import java.lang.ref.Cleaner; -import java.lang.ref.ReferenceQueue; -import java.util.Map; -import java.util.function.Supplier; - -import jdk.graal.compiler.word.Word; -import org.graalvm.jniutils.JNI; -import org.graalvm.jniutils.JNIExceptionWrapper; -import org.graalvm.jniutils.JNIMethodScope; -import org.graalvm.jniutils.JNIUtil; -import org.graalvm.nativeimage.CurrentIsolate; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.LogHandler; -import org.graalvm.nativeimage.Platform.HOSTED_ONLY; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.StackValue; -import org.graalvm.nativeimage.VMRuntime; -import org.graalvm.nativeimage.hosted.FieldValueTransformer; -import org.graalvm.nativeimage.impl.IsolateSupport; -import org.graalvm.word.Pointer; - -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.Delete; -import com.oracle.svm.core.annotate.Inject; -import com.oracle.svm.core.annotate.RecomputeFieldValue; -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.annotate.TargetElement; -import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.c.CGlobalDataFactory; -import com.oracle.svm.core.heap.GCCause; -import com.oracle.svm.core.heap.Heap; -import com.oracle.svm.core.jdk.JDKLatest; -import com.oracle.svm.core.log.FunctionPointerLogHandler; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.graal.hotspot.LibGraalJNIMethodScope; - -class LibGraalJVMCISubstitutions { - - @TargetClass(className = "jdk.vm.ci.services.Services", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_vm_ci_services_Services { - /** - * Ensures field returns false if seen by the analysis. - */ - // Checkstyle: stop - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// - public static boolean IS_BUILDING_NATIVE_IMAGE = false; - // Checkstyle: resume - - /* - * Static final boolean field Services.IS_IN_NATIVE_IMAGE is used in many places in the - * JVMCI codebase to switch between the different implementations needed for regular use (a - * built-in module jdk.graal.compiler in the JVM) or as part of libgraal. - */ - // Checkstyle: stop - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// - public static boolean IS_IN_NATIVE_IMAGE = true; - // Checkstyle: resume - - /* - * Reset Services.savedProperties to null so that we cannot get the hosted savedProperties - * into the libgraal image-heap. This also guarantees that at libgraal-runtime the - * savedProperties are initialized with the system properties state of the JVM that uses - * libgraal. - */ - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // - private static Map savedProperties; - } - - @TargetClass(className = "jdk.vm.ci.hotspot.Cleaner", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_vm_ci_hotspot_Cleaner { - /* - * Ensure the ReferenceQueue instance in Cleaner.queue that is in libgraal is not - * tainted by any use of the Cleaner class at image build-time. - */ - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, isFinal = true, declClass = ReferenceQueue.class)// - private static ReferenceQueue queue; - - /* - * Make package-private clean() accessible so that it can be called from - * LibGraalEntryPoints.doReferenceHandling(). - */ - @Alias - static native void clean(); - } - - @TargetClass(className = "jdk.vm.ci.hotspot.CompilerToVM", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = {LibGraalFeature.IsEnabled.class, JDKLatest.class}) - static final class Target_jdk_vm_ci_hotspot_CompilerToVM { - /* - * For libgraal the implementation of CompilerToVM.lookupType needs to take into account - * that the passed-in classloader can also be an instance of LibGraalClassLoader. Checking - * if that classLoader is the same as the one of the HotSpotResolvedJavaType class itself - * (which is the LibGraalClassLoader) takes care of that. - */ - @Substitute - Target_jdk_vm_ci_hotspot_HotSpotResolvedJavaType lookupType(ClassLoader classLoader, String name) throws NoClassDefFoundError { - int accessingClassLoader; - if (classLoader == null) { - accessingClassLoader = 0; - } else if (classLoader == ClassLoader.getPlatformClassLoader()) { - accessingClassLoader = 1; - } else if (classLoader == ClassLoader.getSystemClassLoader()) { - accessingClassLoader = 2; - } else if (classLoader == getClass().getClassLoader()) { - accessingClassLoader = 2; - } else { - throw new IllegalArgumentException("Unsupported class loader for lookup: " + classLoader); - } - return lookupType(name, null, 0L, accessingClassLoader, true); - } - - @Alias - native Target_jdk_vm_ci_hotspot_HotSpotResolvedJavaType lookupType(String name, Target_jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl accessingClass, - long accessingKlassPointer, int accessingClassLoader, boolean resolve) throws NoClassDefFoundError; - } - - @TargetClass(className = "jdk.vm.ci.hotspot.HotSpotResolvedJavaType", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_vm_ci_hotspot_HotSpotResolvedJavaType { - } - - @TargetClass(className = "jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl { - } -} - -public class LibGraalSubstitutions { - - private static final String GLOBAL_ATOMIC_LONG = "jdk.graal.compiler.serviceprovider.GlobalAtomicLong"; - - @TargetClass(className = GLOBAL_ATOMIC_LONG, classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_serviceprovider_GlobalAtomicLong { - - @Inject// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = GlobalAtomicLongAddressProvider.class) // - private CGlobalData addressSupplier; - - @Delete private long address; - - /* - * Graal class GlobalAtomicLong uses a java.lang.ref.Cleaner in static field - * GlobalAtomicLong.cleaner to ensure all native memory allocated by GlobalAtomicLong - * instances get freed when the instances are garbage collected. - * - * Native image does not support java.lang.ref.Cleaner. Instead, we can use a - * CGlobalData per GlobalAtomicLong instance if we can guarantee that no instances - * are created at libgraal-runtime. I.e. all GlobalAtomicLongs in the libgraal-image are - * image-heap objects. - */ - @Delete private static Cleaner cleaner; - - /** - * Delete the constructor to ensure instances of {@code GlobalAtomicLong} cannot be created - * at runtime. - */ - @Substitute - @TargetElement(name = TargetElement.CONSTRUCTOR_NAME) - @SuppressWarnings({"unused", "static-method"}) - public void constructor(long initialValue) { - throw VMError.unsupportedFeature("Cannot create " + GLOBAL_ATOMIC_LONG + " objects in native image runtime"); - } - - @Substitute - private long getAddress() { - return addressSupplier.get().rawValue(); - } - } - - /* - * The challenge with using CGlobalData for GlobalAtomicLongs is that we do have to - * make sure they get initialized with the correct initialValue for a given GlobalAtomicLong - * instance at image build-time. This FieldValueTransformer ensures that. - */ - @Platforms(HOSTED_ONLY.class) - private static final class GlobalAtomicLongAddressProvider implements FieldValueTransformer { - @Override - public Object transform(Object receiver, Object originalValue) { - long initialValue; - try { - initialValue = (long) ImageSingletons.lookup(LibGraalFeature.class).handleGlobalAtomicLongGetInitialValue.invoke(receiver); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); - } - return CGlobalDataFactory.createWord(Word.unsigned(initialValue), null, true); - } - } - - @TargetClass(className = "jdk.graal.compiler.serviceprovider.VMSupport", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_serviceprovider_VMSupport { - - @Substitute - public static long getIsolateAddress() { - return CurrentIsolate.getIsolate().rawValue(); - } - - @Substitute - public static long getIsolateID() { - return ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); - } - - /** - * Performs the following actions around a libgraal compilation: - *
    - *
  • before: opens a JNIMethodScope to allow Graal compilations of Truffle host methods to - * call methods on the TruffleCompilerRuntime.
  • - *
  • after: closes the above JNIMethodScope
  • - *
  • after: triggers GC weak reference processing as SVM does not use a separate thread - * for this in libgraal
  • - *
- */ - static class LibGraalCompilationRequestScope implements AutoCloseable { - final JNIMethodScope scope; - - LibGraalCompilationRequestScope() { - JNI.JNIEnv env = LibGraalEntryPoints.getJNIEnv(); - /* - * This scope is required to allow Graal compilations of host methods to call - * methods in the TruffleCompilerRuntime. This is, for example, required to find out - * about Truffle-specific method annotations. - */ - scope = LibGraalJNIMethodScope.open("", env, false); - } - - @Override - public void close() { - try { - if (scope != null) { - scope.close(); - } - } finally { - /* - * libgraal doesn't use a dedicated reference handler thread, so we trigger the - * reference handling manually when a compilation finishes. - */ - LibGraalEntryPoints.doReferenceHandling(); - } - } - } - - @Substitute - public static AutoCloseable getCompilationRequestScope() { - return new LibGraalCompilationRequestScope(); - } - - @Substitute - public static void fatalError(String message, int delayMS) { - LogHandler handler = ImageSingletons.lookup(LogHandler.class); - if (handler instanceof FunctionPointerLogHandler) { - try { - Thread.sleep(delayMS); - } catch (InterruptedException e) { - // ignore - } - VMError.shouldNotReachHere(message); - } - } - - @Substitute - public static void startupLibGraal() { - VMRuntime.initialize(); - } - - @Substitute - public static void shutdownLibGraal() { - VMRuntime.shutdown(); - } - - @Substitute - public static void invokeShutdownCallback(String cbClassName, String cbMethodName) { - JNI.JNIEnv env = LibGraalEntryPoints.getJNIEnv(); - JNI.JClass cbClass = JNIUtil.findClass(env, JNIUtil.getSystemClassLoader(env), - JNIUtil.getBinaryName(cbClassName), true); - JNI.JMethodID cbMethod = JNIUtil.findMethod(env, cbClass, true, cbMethodName, "()V"); - env.getFunctions().getCallStaticVoidMethodA().call(env, cbClass, cbMethod, StackValue.get(0)); - JNIExceptionWrapper.wrapAndThrowPendingJNIException(env); - } - - @Substitute - public static void notifyLowMemoryPoint(boolean hintFullGC, boolean forceFullGC) { - if (forceFullGC) { - Heap.getHeap().getGC().collectCompletely(GCCause.JavaLangSystemGC); - } else { - Heap.getHeap().getGC().collectionHint(hintFullGC); - } - LibGraalEntryPoints.doReferenceHandling(); - } - } - - @TargetClass(className = "jdk.graal.compiler.phases.BasePhase", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_phases_BasePhase { - - /* - * Redirect method to image build-time pre-computed statistics in LibGraalCompilerSupport. - */ - @Substitute - static Target_jdk_graal_compiler_phases_BasePhase_BasePhaseStatistics getBasePhaseStatistics(Class clazz) { - Object result = LibGraalCompilerSupport.get().getBasePhaseStatistics().get(clazz); - if (result == null) { - throw VMError.shouldNotReachHere(String.format("Missing statistics for phase class: %s%n", clazz.getName())); - } - return SubstrateUtil.cast(result, Target_jdk_graal_compiler_phases_BasePhase_BasePhaseStatistics.class); - } - } - - @TargetClass(className = "jdk.graal.compiler.phases.BasePhase", innerClass = "BasePhaseStatistics", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_phases_BasePhase_BasePhaseStatistics { - } - - @TargetClass(className = "jdk.graal.compiler.lir.phases.LIRPhase", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_lir_phases_LIRPhase { - - /* - * Redirect method to image build-time pre-computed statistics in LibGraalCompilerSupport. - */ - @Substitute - static Target_jdk_graal_compiler_lir_phases_LIRPhase_LIRPhaseStatistics getLIRPhaseStatistics(Class clazz) { - Object result = LibGraalCompilerSupport.get().getLirPhaseStatistics().get(clazz); - if (result == null) { - throw VMError.shouldNotReachHere(String.format("Missing statistics for phase class: %s%n", clazz.getName())); - } - return SubstrateUtil.cast(result, Target_jdk_graal_compiler_lir_phases_LIRPhase_LIRPhaseStatistics.class); - } - } - - @TargetClass(className = "jdk.graal.compiler.lir.phases.LIRPhase", innerClass = "LIRPhaseStatistics", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_lir_phases_LIRPhase_LIRPhaseStatistics { - } - - @TargetClass(className = "jdk.graal.compiler.graph.NodeClass", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_graph_NodeClass { - - @Alias // - private String shortName; - - /* - * All node-classes in libgraal are in the image-heap and were already fully initialized at - * build-time. The shortName accessor method can be reduced to a simple field access. - */ - @Substitute - public String shortName() { - assert shortName != null; - return shortName; - } - } - - @TargetClass(className = "jdk.graal.compiler.hotspot.HotSpotGraalOptionValues", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_hotspot_HotSpotGraalOptionValues { - - @Substitute - private static void notifyLibgraalOptions(Map vmOptionSettings) { - LibGraalEntryPoints.initializeOptions(vmOptionSettings); - } - - @Substitute - private static void printLibgraalProperties(PrintStream out, String prefix) { - LibGraalEntryPoints.printOptions(out, prefix); - } - } - - @TargetClass(className = "jdk.graal.compiler.core.GraalServiceThread", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) - static final class Target_jdk_graal_compiler_core_GraalServiceThread { - @Substitute() - void beforeRun() { - Thread thread = SubstrateUtil.cast(this, Thread.class); - if (!LibGraalEntryPoints.attachCurrentThread(thread.isDaemon(), null)) { - throw new InternalError("Couldn't attach to HotSpot runtime"); - } - } - - @Substitute - @SuppressWarnings("static-method") - void afterRun() { - LibGraalEntryPoints.detachCurrentThread(false); - } - } -} - -/* - * This supplier is used by all LibGraalSubstitutions and ensures that the substitution target - * classes are classes from the LibGraalClassLoader (instead of hosted Graal & JVMCI classes). - */ -@Platforms(HOSTED_ONLY.class) -class LibGraalClassLoaderSupplier implements Supplier { - @Override - public ClassLoader get() { - ClassLoader loader = ImageSingletons.lookup(LibGraalFeature.class).loader; - VMError.guarantee(loader != null); - return loader; - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/NativeImageHostEntryPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/NativeImageHostEntryPoints.java deleted file mode 100644 index a68f623c7d65..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/NativeImageHostEntryPoints.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import org.graalvm.jniutils.HSObject; -import org.graalvm.jniutils.JNI.JObject; -import org.graalvm.jniutils.JNIMethodScope; -import org.graalvm.jniutils.JNIUtil; - -import com.oracle.truffle.compiler.TruffleCompilerOptionDescriptor; - -import jdk.graal.compiler.word.Word; - -/** - * Entry points for native-image specific methods called by guest Graal using method handles. - */ -public final class NativeImageHostEntryPoints { - - private NativeImageHostEntryPoints() { - } - - public static void initializeHost(long runtimeClass) { - TruffleFromLibGraalStartPoints.initializeJNI(Word.pointer(runtimeClass)); - } - - public static Object createLocalHandleForLocalReference(long jniLocalRef) { - JNIMethodScope scope = JNIMethodScope.scopeOrNull(); - if (scope == null) { - return null; - } - return new HSObject(scope, Word.pointer(jniLocalRef)); - } - - public static Object createLocalHandleForWeakGlobalReference(long jniWeakGlobalRef) { - JNIMethodScope scope = JNIMethodScope.scope(); - JObject localRef = JNIUtil.NewLocalRef(scope.getEnv(), Word.pointer(jniWeakGlobalRef)); - return localRef.isNull() ? null : new HSObject(scope, localRef); - } - - public static Object createGlobalHandle(Object hsHandle, boolean allowGlobalDuplicates) { - if (hsHandle == null) { - return null; - } - return new HSObject(JNIMethodScope.env(), ((HSObject) hsHandle).getHandle(), allowGlobalDuplicates, false); - } - - public static boolean isSameObject(Object o1, Object o2) { - return JNIUtil.IsSameObject(JNIMethodScope.env(), ((HSObject) o1).getHandle(), ((HSObject) o2).getHandle()); - } - - public static long getObjectClass(Object o) { - return JNIUtil.GetObjectClass(JNIMethodScope.env(), ((HSObject) o).getHandle()).rawValue(); - } - - public static Object createTruffleCompilerOptionDescriptor(String name, int type, boolean deprecated, String help, String deprecationMessage) { - return new TruffleCompilerOptionDescriptor(name, TruffleCompilerOptionDescriptor.Type.values()[type], deprecated, help, deprecationMessage); - } - - public static void onCompilationSuccess(Object hsHandle, int tier, boolean lastTier) { - TruffleFromLibGraalStartPoints.onCompilationSuccess(hsHandle, tier, lastTier); - } -} diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalStartPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalStartPoints.java deleted file mode 100644 index b58948e39716..000000000000 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalStartPoints.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.graal.hotspot.libgraal; - -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callAddInlinedTarget; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callAddTargetToDequeue; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callAsJavaConstant; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callCancelCompilation; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callCompilableToString; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callConsumeOptimizedAssumptionDependency; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callCountDirectCallNodes; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callCreateStringSupplier; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callEngineId; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetCompilableCallCount; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetCompilableName; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetCompilerOptions; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetConstantFieldInfo; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetDebugProperties; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetDescription; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetFailedSpeculationsAddress; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetKnownCallSiteCount; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetLanguage; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetLineNumber; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetNodeClassName; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetNodeId; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetNonTrivialNodeCount; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetOffsetEnd; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetOffsetStart; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetPartialEvaluationMethodInfo; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetPosition; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetSuppliedString; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callGetURI; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callHasNextTier; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsCancelled; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsLastTier; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsSameOrSplit; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsSuppressedFailure; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsTrivial; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callIsValueType; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callLog; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnCodeInstallation; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnCompilationFailed; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnCompilationRetry; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnFailure; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnGraalTierFinished; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnIsolateShutdown; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnSuccess; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callOnTruffleTierFinished; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callPrepareForCompilation; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callRegisterOptimizedAssumptionDependency; -import static com.oracle.svm.graal.hotspot.libgraal.TruffleFromLibGraalStartPointsGen.callSetCallCounts; -import static org.graalvm.jniutils.JNIMethodScope.env; -import static org.graalvm.jniutils.JNIUtil.ExceptionClear; -import static org.graalvm.jniutils.JNIUtil.GetStaticMethodID; -import static org.graalvm.jniutils.JNIUtil.createString; -import static org.graalvm.nativeimage.c.type.CTypeConversion.toCString; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.graalvm.jniutils.HSObject; -import org.graalvm.jniutils.JNI.JByteArray; -import org.graalvm.jniutils.JNI.JClass; -import org.graalvm.jniutils.JNI.JMethodID; -import org.graalvm.jniutils.JNI.JNIEnv; -import org.graalvm.jniutils.JNI.JObject; -import org.graalvm.jniutils.JNI.JValue; -import org.graalvm.jniutils.JNI.JavaVM; -import org.graalvm.jniutils.JNICalls.JNIMethod; -import org.graalvm.jniutils.JNIMethodScope; -import org.graalvm.jniutils.JNIUtil; -import org.graalvm.nativebridge.BinaryInput; -import org.graalvm.nativeimage.StackValue; -import org.graalvm.nativeimage.c.type.CCharPointer; -import org.graalvm.nativeimage.c.type.CTypeConversion; - -import com.oracle.truffle.compiler.hotspot.libgraal.FromLibGraalId; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; - -import jdk.graal.compiler.word.Word; - -/** - * JNI calls to HotSpot called by guest Graal using method handles. - */ -public final class TruffleFromLibGraalStartPoints { - - private static volatile TruffleFromLibGraalCalls calls; - private static JavaVM javaVM; - - private TruffleFromLibGraalStartPoints() { - } - - static void initializeJNI(JClass runtimeClass) { - TruffleFromLibGraalCalls localCalls = calls; - if (localCalls == null) { - initialize(runtimeClass); - } - } - - private static synchronized void initialize(JClass runtimeClass) { - calls = new TruffleFromLibGraalCalls(JNIMethodScope.env(), runtimeClass); - JavaVM vm = JNIUtil.GetJavaVM(JNIMethodScope.env()); - assert javaVM.isNull() || javaVM.equal(vm); - javaVM = vm; - } - - @TruffleFromLibGraal(Id.OnIsolateShutdown) - public static void onIsolateShutdown(long isolateId) { - JNIEnv env = JNIUtil.GetEnv(javaVM); - callOnIsolateShutdown(calls, env, isolateId); - } - - @TruffleFromLibGraal(Id.GetPartialEvaluationMethodInfo) - public static byte[] getPartialEvaluationMethodInfo(Object hsHandle, long methodHandle) { - JNIEnv env = JNIMethodScope.env(); - JByteArray hsByteArray = callGetPartialEvaluationMethodInfo(calls, env, ((HSObject) hsHandle).getHandle(), methodHandle); - CCharPointer buffer = StackValue.get(5); - JNIUtil.GetByteArrayRegion(env(), hsByteArray, 0, 5, buffer); - BinaryInput in = BinaryInput.create(buffer, 5); - return new byte[]{ - in.readByte(), - in.readByte(), - in.readByte(), - (byte) (in.readBoolean() ? 1 : 0), - (byte) (in.readBoolean() ? 1 : 0), - }; - } - - @TruffleFromLibGraal(Id.OnCodeInstallation) - public static void onCodeInstallation(Object hsHandle, Object compilableHsHandle, long installedCodeHandle) { - JNIEnv env = JNIMethodScope.env(); - callOnCodeInstallation(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle(), installedCodeHandle); - } - - @TruffleFromLibGraal(Id.RegisterOptimizedAssumptionDependency) - public static Object registerOptimizedAssumptionDependency(Object hsHandle, long optimizedAssumptionHandle) { - JNIMethodScope scope = JNIMethodScope.scope(); - JObject assumptionConsumer = callRegisterOptimizedAssumptionDependency(calls, scope.getEnv(), ((HSObject) hsHandle).getHandle(), optimizedAssumptionHandle); - return assumptionConsumer.isNull() ? null : new HSObject(scope, assumptionConsumer); - } - - @TruffleFromLibGraal(Id.IsValueType) - public static boolean isValueType(Object hsHandle, long typeHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsValueType(calls, env, ((HSObject) hsHandle).getHandle(), typeHandle); - } - - @TruffleFromLibGraal(Id.GetConstantFieldInfo) - public static int getConstantFieldInfo(Object hsHandle, long typeHandle, boolean isStatic, int fieldIndex) { - JNIEnv env = JNIMethodScope.env(); - return callGetConstantFieldInfo(calls, env, ((HSObject) hsHandle).getHandle(), typeHandle, isStatic, fieldIndex); - } - - @TruffleFromLibGraal(Id.Log) - public static void log(Object hsHandle, String loggerId, Object compilableHsHandle, String message) { - JNIEnv env = JNIMethodScope.env(); - callLog(calls, env, ((HSObject) hsHandle).getHandle(), JNIUtil.createHSString(env, loggerId), ((HSObject) compilableHsHandle).getHandle(), JNIUtil.createHSString(env, message)); - } - - @TruffleFromLibGraal(Id.CreateStringSupplier) - public static Object createStringSupplier(Object serializedException) { - JNIMethodScope scope = JNIMethodScope.scope(); - long serializedExceptionHandle = LibGraalObjectHandles.create(serializedException); - return new HSObject(scope, callCreateStringSupplier(calls, scope.getEnv(), serializedExceptionHandle)); - } - - @TruffleFromLibGraal(Id.GetSuppliedString) - public static String getSuppliedString(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return createString(env, callGetSuppliedString(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.IsSuppressedFailure) - public static boolean isSuppressedFailure(Object hsHandle, Object compilableHsHandle, Object supplierHsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsSuppressedFailure(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle(), ((HSObject) supplierHsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetFailedSpeculationsAddress) - public static long getFailedSpeculationsAddress(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetFailedSpeculationsAddress(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetCompilerOptions) - public static Map getCompilerOptions(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - JByteArray res = callGetCompilerOptions(calls, env, ((HSObject) hsHandle).getHandle()); - BinaryInput in = BinaryInput.create(JNIUtil.createArray(env, res)); - int size = in.readInt(); - Map map = new LinkedHashMap<>(); - for (int i = 0; i < size; i++) { - String key = in.readUTF(); - map.put(key, in.readUTF()); - } - return map; - } - - @TruffleFromLibGraal(Id.EngineId) - public static long engineId(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callEngineId(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.PrepareForCompilation) - public static boolean prepareForCompilation(Object hsHandle, boolean p1, int p2, boolean p3) { - JNIEnv env = JNIMethodScope.env(); - JNIMethod newMethod = findPrepareForCompilationNewMethod(env); - if (newMethod != null) { - return callPrepareForCompilationNew(newMethod, env, ((HSObject) hsHandle).getHandle(), p1, p2, p3); - } else { - callPrepareForCompilation(calls, env, ((HSObject) hsHandle).getHandle()); - return true; - } - } - - private static volatile JNIMethod prepareForCompilationNewMethod; - - private static JNIMethod findPrepareForCompilationNewMethod(JNIEnv env) { - JNIMethod res = prepareForCompilationNewMethod; - if (res == null) { - res = findJNIMethod(env, "prepareForCompilation", boolean.class, Object.class, boolean.class, int.class, boolean.class); - prepareForCompilationNewMethod = res; - } - return res.getJMethodID().isNonNull() ? res : null; - } - - static boolean callPrepareForCompilationNew(JNIMethod method, JNIEnv env, JObject p0, boolean p1, int p2, boolean p3) { - JValue args = StackValue.get(4, JValue.class); - args.addressOf(0).setJObject(p0); - args.addressOf(1).setBoolean(p1); - args.addressOf(2).setInt(p2); - args.addressOf(3).setBoolean(p3); - return calls.getJNICalls().callStaticBoolean(env, calls.getPeer(), method, args); - } - - private static JNIMethod findJNIMethod(JNIEnv env, String methodName, Class returnType, Class... parameterTypes) { - try (CTypeConversion.CCharPointerHolder cname = toCString(methodName); - CTypeConversion.CCharPointerHolder csig = toCString(FromLibGraalId.encodeMethodSignature(returnType, parameterTypes))) { - JMethodID jniId = GetStaticMethodID(env, calls.getPeer(), cname.get(), csig.get()); - if (jniId.isNull()) { - /* - * The `onFailure` method with 7 arguments is not available in Truffle runtime 24.0, - * clear pending NoSuchMethodError. - */ - ExceptionClear(env); - } - return new JNIMethod() { - @Override - public JMethodID getJMethodID() { - return jniId; - } - - @Override - public String getDisplayName() { - return methodName; - } - }; - } - } - - @TruffleFromLibGraal(Id.IsTrivial) - public static boolean isTrivial(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsTrivial(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.AsJavaConstant) - public static long asJavaConstant(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callAsJavaConstant(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.OnCompilationFailed) - public static void onCompilationFailed(Object hsHandle, Object serializedExceptionHsHandle, boolean suppressed, boolean bailout, boolean permanentBailout, boolean graphTooBig) { - JNIEnv env = JNIMethodScope.env(); - callOnCompilationFailed(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) serializedExceptionHsHandle).getHandle(), - suppressed, bailout, permanentBailout, graphTooBig); - } - - private static volatile JNIMethod onCompilationSuccessMethod; - - private static JNIMethod findOnCompilationSuccessMethod(JNIEnv env) { - JNIMethod res = onCompilationSuccessMethod; - if (res == null) { - res = findJNIMethod(env, "onCompilationSuccess", void.class, Object.class, int.class, boolean.class); - onCompilationSuccessMethod = res; - } - return res.getJMethodID().isNonNull() ? res : null; - } - - public static void onCompilationSuccess(Object hsHandle, int compilationTier, boolean lastTier) { - JNIEnv env = JNIMethodScope.env(); - JNIMethod methodOrNull = findOnCompilationSuccessMethod(env); - if (methodOrNull != null) { - JValue args = StackValue.get(3, JValue.class); - args.addressOf(0).setJObject(((HSObject) hsHandle).getHandle()); - args.addressOf(1).setInt(compilationTier); - args.addressOf(2).setBoolean(lastTier); - calls.getJNICalls().callStaticVoid(env, calls.getPeer(), methodOrNull, args); - } - } - - @TruffleFromLibGraal(Id.GetCompilableName) - public static String getCompilableName(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return createString(env, callGetCompilableName(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.GetNonTrivialNodeCount) - public static int getNonTrivialNodeCount(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetNonTrivialNodeCount(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.CountDirectCallNodes) - public static int countDirectCallNodes(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callCountDirectCallNodes(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetCompilableCallCount) - public static int getCompilableCallCount(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetCompilableCallCount(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.CompilableToString) - public static String compilableToString(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return createString(env, callCompilableToString(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.CancelCompilation) - public static boolean cancelCompilation(Object hsHandle, CharSequence reason) { - JNIEnv env = JNIMethodScope.env(); - return callCancelCompilation(calls, env, ((HSObject) hsHandle).getHandle(), JNIUtil.createHSString(env, reason.toString())); - } - - @TruffleFromLibGraal(Id.IsSameOrSplit) - public static boolean isSameOrSplit(Object hsHandle, Object otherHsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsSameOrSplit(calls, env, ((HSObject) hsHandle).getHandle(), - otherHsHandle == null ? Word.nullPointer() : ((HSObject) otherHsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetKnownCallSiteCount) - public static int getKnownCallSiteCount(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetKnownCallSiteCount(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.ConsumeOptimizedAssumptionDependency) - public static void consumeOptimizedAssumptionDependency(Object hsHandle, Object compilableHsHandle, long installedCode) { - JNIEnv env = JNIMethodScope.env(); - callConsumeOptimizedAssumptionDependency(calls, env, ((HSObject) hsHandle).getHandle(), - compilableHsHandle == null ? Word.nullPointer() : ((HSObject) compilableHsHandle).getHandle(), - installedCode); - } - - @TruffleFromLibGraal(Id.IsCancelled) - public static boolean isCancelled(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsCancelled(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.IsLastTier) - public static boolean isLastTier(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callIsLastTier(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.HasNextTier) - public static boolean hasNextTier(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callHasNextTier(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetPosition) - public static Object getPosition(Object hsHandle, long nodeHandle) { - JNIMethodScope scope = JNIMethodScope.scope(); - JObject hsPosition = callGetPosition(calls, scope.getEnv(), ((HSObject) hsHandle).getHandle(), nodeHandle); - if (hsPosition.isNull()) { - return null; - } else { - return new HSObject(scope, hsPosition); - } - } - - @TruffleFromLibGraal(Id.AddTargetToDequeue) - public static void addTargetToDequeue(Object hsHandle, Object compilableHsHandle) { - JNIEnv env = JNIMethodScope.env(); - callAddTargetToDequeue(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.SetCallCounts) - public static void setCallCounts(Object hsHandle, int total, int inlined) { - JNIEnv env = JNIMethodScope.env(); - callSetCallCounts(calls, env, ((HSObject) hsHandle).getHandle(), total, inlined); - } - - @TruffleFromLibGraal(Id.AddInlinedTarget) - public static void addInlinedTarget(Object hsHandle, Object compilableHsHandle) { - JNIEnv env = JNIMethodScope.env(); - callAddInlinedTarget(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetDebugProperties) - public static Map getDebugProperties(Object hsHandle, long nodeHandle) { - JNIEnv env = JNIMethodScope.env(); - byte[] bytes = JNIUtil.createArray(env, (JByteArray) callGetDebugProperties(calls, env, ((HSObject) hsHandle).getHandle(), nodeHandle)); - BinaryInput in = BinaryInput.create(bytes); - Map result = new LinkedHashMap<>(); - int size = in.readInt(); - for (int i = 0; i < size; i++) { - String key = in.readUTF(); - Object value = in.readTypedValue(); - result.put(key, value); - } - return result; - } - - @TruffleFromLibGraal(Id.OnSuccess) - public static void onSuccess(Object hsHandle, Object compilableHsHandle, Object taskHsHandle, Object graphInfo, Object compilationResultInfo, int tier) { - try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graphInfo); - LibGraalObjectHandleScope compilationResultInfoScope = LibGraalObjectHandleScope.forObject(compilationResultInfo)) { - JNIEnv env = JNIMethodScope.env(); - callOnSuccess(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle(), - ((HSObject) taskHsHandle).getHandle(), graphInfoScope.getHandle(), compilationResultInfoScope.getHandle(), - tier); - } - } - - @TruffleFromLibGraal(Id.OnTruffleTierFinished) - public static void onTruffleTierFinished(Object hsHandle, Object compilableHsHandle, Object taskHsHandle, Object graphInfo) { - try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graphInfo)) { - JNIEnv env = JNIMethodScope.env(); - callOnTruffleTierFinished(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle(), - ((HSObject) taskHsHandle).getHandle(), graphInfoScope.getHandle()); - } - } - - @TruffleFromLibGraal(Id.OnGraalTierFinished) - public static void onGraalTierFinished(Object hsHandle, Object compilableHsHandle, Object graphInfo) { - try (LibGraalObjectHandleScope graphInfoScope = LibGraalObjectHandleScope.forObject(graphInfo)) { - JNIEnv env = JNIMethodScope.env(); - callOnGraalTierFinished(calls, env, ((HSObject) hsHandle).getHandle(), ((HSObject) compilableHsHandle).getHandle(), - graphInfoScope.getHandle()); - } - } - - @TruffleFromLibGraal(Id.OnFailure) - public static void onFailure(Object hsHandle, Object compilableHsHandle, String reason, boolean bailout, boolean permanentBailout, int tier, Object lazyStackTrace) { - try (LibGraalObjectHandleScope lazyStackTraceScope = lazyStackTrace != null ? LibGraalObjectHandleScope.forObject(lazyStackTrace) : null) { - JNIEnv env = JNIMethodScope.env(); - callOnFailure(calls, env, ((HSObject) hsHandle).getHandle(), - ((HSObject) compilableHsHandle).getHandle(), JNIUtil.createHSString(env, reason), - bailout, permanentBailout, tier, lazyStackTraceScope != null ? lazyStackTraceScope.getHandle() : 0L); - } - } - - @TruffleFromLibGraal(Id.OnCompilationRetry) - public static void onCompilationRetry(Object hsHandle, Object compilableHsHandle, Object taskHsHandle) { - JNIEnv env = JNIMethodScope.env(); - callOnCompilationRetry(calls, env, ((HSObject) hsHandle).getHandle(), - ((HSObject) compilableHsHandle).getHandle(), ((HSObject) taskHsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetOffsetStart) - public static int getOffsetStart(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetOffsetStart(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetOffsetEnd) - public static int getOffsetEnd(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetOffsetEnd(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetLineNumber) - public static int getLineNumber(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetLineNumber(calls, env, ((HSObject) hsHandle).getHandle()); - } - - @TruffleFromLibGraal(Id.GetLanguage) - public static String getLanguage(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return JNIUtil.createString(env, callGetLanguage(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.GetDescription) - public static String getDescription(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return JNIUtil.createString(env, callGetDescription(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.GetURI) - public static String getURI(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return JNIUtil.createString(env, callGetURI(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.GetNodeClassName) - public static String getNodeClassName(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return JNIUtil.createString(env, callGetNodeClassName(calls, env, ((HSObject) hsHandle).getHandle())); - } - - @TruffleFromLibGraal(Id.GetNodeId) - public static int getNodeId(Object hsHandle) { - JNIEnv env = JNIMethodScope.env(); - return callGetNodeId(calls, env, ((HSObject) hsHandle).getHandle()); - } -} diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java index 84adac791e33..d5112144f8a9 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java @@ -121,7 +121,7 @@ protected void parseRetryOptions(String[] options, EconomicMap, Obj @SuppressWarnings("try") @Override protected CompilationResult performCompilation(DebugContext debug) { - try (CompilationWatchDog watchdog = CompilationWatchDog.watch(compilationId, debug.getOptions(), false, COMPILATION_WATCH_DOG_EVENT_HANDLER)) { + try (CompilationWatchDog watchdog = CompilationWatchDog.watch(compilationId, debug.getOptions(), false, COMPILATION_WATCH_DOG_EVENT_HANDLER, null)) { StructuredGraph graph = TruffleRuntimeCompilationSupport.decodeGraph(debug, null, compilationId, method, null); return compileGraph(runtimeConfig, TruffleRuntimeCompilationSupport.getMatchingSuitesForGraph(graph), lirSuites, method, graph); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/FieldsOffsetsFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/FieldsOffsetsFeature.java index dea96dff84b1..3014f6dd3c9f 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/FieldsOffsetsFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/FieldsOffsetsFeature.java @@ -41,10 +41,8 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.graal.GraalCompilerSupport; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; -import com.oracle.svm.hosted.FeatureImpl.CompilationAccessImpl; import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; -import com.oracle.svm.hosted.meta.HostedMetaAccess; import jdk.graal.compiler.core.common.FieldIntrospection; import jdk.graal.compiler.core.common.Fields; @@ -53,7 +51,6 @@ import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.lir.LIRInstruction; import jdk.graal.compiler.lir.LIRInstructionClass; -import jdk.internal.misc.Unsafe; /** * Graal uses unsafe memory accesses to access {@link Node}s and {@link LIRInstruction}s. The @@ -64,7 +61,7 @@ */ public class FieldsOffsetsFeature implements Feature { - abstract static class IterationMaskRecomputation implements FieldValueTransformerWithAvailability { + public static class IterationMaskRecomputation implements FieldValueTransformerWithAvailability { @Override public boolean isAvailable() { return BuildPhaseProvider.isHostedUniverseBuilt(); @@ -72,33 +69,16 @@ public boolean isAvailable() { @Override public Object transform(Object receiver, Object originalValue) { - Edges edges = getEdges((NodeClass) receiver); + Edges edges = (Edges) receiver; FieldsOffsetsReplacement replacement = FieldsOffsetsFeature.getReplacements().get(edges.getOffsets()); assert replacement.fields == edges; - assert replacement.newValuesAvailable : "Cannot access iteration mask before field offsets are assigned"; + assert replacement.newOffsets != null : "Cannot access iteration mask before field offsets are assigned"; return replacement.newIterationInitMask; } - - protected abstract Edges getEdges(NodeClass nodeClass); - } - - public static class InputsIterationMaskRecomputation extends IterationMaskRecomputation { - @Override - protected Edges getEdges(NodeClass nodeClass) { - return nodeClass.getInputEdges(); - } - } - - public static class SuccessorsIterationMaskRecomputation extends IterationMaskRecomputation { - @Override - protected Edges getEdges(NodeClass nodeClass) { - return nodeClass.getSuccessorEdges(); - } } static class FieldsOffsetsReplacement { protected final Fields fields; - protected boolean newValuesAvailable; protected long[] newOffsets; protected long newIterationInitMask; @@ -144,7 +124,7 @@ private static Object replaceFieldsOffsets(Object source) { * the hosted offsets so that we have a return value. The actual offsets do not * matter at this point. */ - if (replacement.newValuesAvailable) { + if (replacement.newOffsets != null) { return replacement.newOffsets; } } @@ -228,25 +208,10 @@ private static Field findField(Fields fields, int index) { @Override public void beforeCompilation(BeforeCompilationAccess a) { - CompilationAccessImpl config = (CompilationAccessImpl) a; - HostedMetaAccess hMetaAccess = config.getMetaAccess(); - for (FieldsOffsetsReplacement replacement : getReplacements().values()) { - Fields fields = replacement.fields; - long[] newOffsets = new long[fields.getCount()]; - for (int i = 0; i < newOffsets.length; i++) { - Field field = findField(fields, i); - assert Unsafe.getUnsafe().objectFieldOffset(field) == fields.getOffsets()[i]; - newOffsets[i] = hMetaAccess.lookupJavaField(field).getLocation(); - } - replacement.newOffsets = newOffsets; - - if (fields instanceof Edges) { - Edges edges = (Edges) fields; - replacement.newIterationInitMask = NodeClass.computeIterationMask(edges.type(), edges.getDirectCount(), newOffsets); - } - - replacement.newValuesAvailable = true; + Map.Entry e = replacement.fields.recomputeOffsetsAndIterationMask(a::objectFieldOffset); + replacement.newOffsets = e.getKey(); + replacement.newIterationInitMask = e.getValue(); } ImageSingletons.lookup(FieldsOffsetsReplacements.class).newValuesAvailable = true; } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalCompilerFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalCompilerFeature.java index 5ed05c456eef..b659e1c70cf4 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalCompilerFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalCompilerFeature.java @@ -28,8 +28,12 @@ import java.util.List; import java.util.function.BooleanSupplier; +import com.oracle.svm.util.ReflectionUtil; +import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.FieldValueTransformer; import org.graalvm.nativeimage.hosted.RuntimeReflection; import com.oracle.svm.core.feature.InternalFeature; @@ -42,7 +46,7 @@ /** * This feature is used to contain functionality needed when a Graal compiler is included in a - * native-image. This is used by RuntimeCompilation and LibGraal. + * native-image. This is used by RuntimeCompilation but not LibGraalFeature. */ public class GraalCompilerFeature implements InternalFeature { @@ -65,10 +69,23 @@ public void duringSetup(DuringSetupAccess c) { ((FeatureImpl.DuringSetupAccessImpl) c).registerClassReachabilityListener(GraalCompilerSupport::registerPhaseStatistics); } + static class GlobalAtomicLongTransformer implements FieldValueTransformer { + void register(BeforeAnalysisAccess access) { + access.registerFieldValueTransformer(ReflectionUtil.lookupField(GlobalAtomicLong.class, "addressSupplier"), this); + } + + @Override + public Object transform(Object receiver, Object originalValue) { + return GlobalData.createGlobal(((GlobalAtomicLong) receiver).getInitialValue()); + } + } + @Override public void beforeAnalysis(BeforeAnalysisAccess c) { DebugContext debug = DebugContext.forCurrentThread(); + new GlobalAtomicLongTransformer().register(c); + // box lowering accesses the caches for those classes and thus needs reflective access for (JavaKind kind : new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Double, JavaKind.Float, JavaKind.Int, JavaKind.Long, JavaKind.Short}) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java index 5274351b5827..af1702a2dbb3 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java @@ -76,7 +76,6 @@ import jdk.graal.compiler.api.runtime.GraalRuntime; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.debug.MetricKey; -import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotBackendFactory; import jdk.graal.compiler.hotspot.SnippetResolvedJavaMethod; @@ -170,8 +169,7 @@ public Object apply(Object source) { throw new UnsupportedFeatureException("JVMCIRuntime should not appear in the image: " + source); } else if (source instanceof GraalHotSpotVMConfig) { throw new UnsupportedFeatureException("GraalHotSpotVMConfig should not appear in the image: " + source); - } else if (source instanceof HotSpotBackendFactory) { - HotSpotBackendFactory factory = (HotSpotBackendFactory) source; + } else if (source instanceof HotSpotBackendFactory factory) { Architecture hostArch = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch; if (!factory.getArchitecture().equals(hostArch.getName())) { throw new UnsupportedFeatureException("Non-host architecture HotSpotBackendFactory should not appear in the image: " + source); @@ -190,9 +188,6 @@ public Object apply(Object source) { } else if (source instanceof MetricKey) { /* Ensure lazily initialized name fields are computed. */ ((MetricKey) source).getName(); - } else if (source instanceof NodeClass) { - /* Ensure lazily initialized shortName field is computed. */ - ((NodeClass) source).shortName(); } else if (source instanceof ResolvedJavaMethod) { if (source instanceof OriginalMethodProvider) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java index 670bc0cf9f0e..4f9a2c576a5b 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java @@ -28,34 +28,28 @@ import static com.oracle.svm.core.annotate.RecomputeFieldValue.Kind.FromAlias; import java.io.PrintStream; -import java.lang.ref.Cleaner; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import jdk.graal.compiler.word.Word; +import com.oracle.svm.core.Isolates; +import jdk.graal.compiler.graph.Edges; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.FieldValueTransformer; -import org.graalvm.nativeimage.impl.IsolateSupport; -import org.graalvm.word.Pointer; import com.oracle.svm.core.SubstrateTargetDescription; import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.Delete; import com.oracle.svm.core.annotate.Inject; import com.oracle.svm.core.annotate.InjectAccessors; import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.annotate.TargetElement; -import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.c.CGlobalDataFactory; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.option.HostedOptionValues; @@ -79,7 +73,6 @@ import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.debug.TimeSource; import jdk.graal.compiler.graph.Node; -import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool; import jdk.graal.compiler.lir.phases.LIRPhase; import jdk.graal.compiler.nodes.Invoke; @@ -96,7 +89,6 @@ import jdk.graal.compiler.printer.NoDeadCodeVerifyHandler; import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode; import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode; -import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -226,43 +218,7 @@ public static long getIsolateAddress() { @Substitute public static long getIsolateID() { - return ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); - } -} - -class GlobalAtomicLongAddressProvider implements FieldValueTransformer { - @Override - public Object transform(Object receiver, Object originalValue) { - long initialValue = ((GlobalAtomicLong) receiver).getInitialValue(); - return CGlobalDataFactory.createWord(Word.unsigned(initialValue), null, true); - } -} - -@TargetClass(className = "jdk.graal.compiler.serviceprovider.GlobalAtomicLong", onlyWith = GraalCompilerFeature.IsEnabled.class) -final class Target_jdk_graal_compiler_serviceprovider_GlobalAtomicLong { - - @Inject// - @RecomputeFieldValue(kind = Kind.Custom, declClass = GlobalAtomicLongAddressProvider.class) // - private CGlobalData addressSupplier; - - @Delete private long address; - - @Delete private static Cleaner cleaner; - - /** - * Delete the constructor to ensure instances of {@link GlobalAtomicLong} cannot be created at - * runtime. - */ - @Substitute - @TargetElement(name = TargetElement.CONSTRUCTOR_NAME) - @SuppressWarnings({"unused", "static-method"}) - public void constructor(long initialValue) { - throw VMError.unsupportedFeature("Cannot create " + GlobalAtomicLong.class.getName() + " objects in native image runtime"); - } - - @Substitute - private long getAddress() { - return addressSupplier.get().rawValue(); + return Isolates.getIsolateId(); } } @@ -348,25 +304,11 @@ static LIRPhase.LIRPhaseStatistics getLIRPhaseStatistics(Class clazz) { } } -@TargetClass(value = NodeClass.class, onlyWith = GraalCompilerFeature.IsEnabled.class) -final class Target_jdk_graal_compiler_graph_NodeClass { - +@TargetClass(value = Edges.class, onlyWith = GraalCompilerFeature.IsEnabled.class) +final class Target_jdk_graal_compiler_graph_Edges { @Alias// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = FieldsOffsetsFeature.InputsIterationMaskRecomputation.class)// - private long inputsIteration; - - @Alias// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = FieldsOffsetsFeature.SuccessorsIterationMaskRecomputation.class)// - private long successorIteration; - - @Alias // - private String shortName; - - @Substitute - public String shortName() { - assert shortName != null; - return shortName; - } + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = FieldsOffsetsFeature.IterationMaskRecomputation.class)// + private long iterationMask; } @TargetClass(value = NoDeadCodeVerifyHandler.class) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java index 7547acc7b334..f5a64d90ca28 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java @@ -41,7 +41,7 @@ import com.oracle.svm.hosted.jdk.HostedClassLoaderPackageManagement; import com.oracle.svm.util.ReflectionUtil; -import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import jdk.internal.loader.ClassLoaders; import jdk.vm.ci.meta.JavaConstant; @@ -121,19 +121,10 @@ public void duringSetup(DuringSetupAccess access) { var config = (FeatureImpl.DuringSetupAccessImpl) access; if (ImageLayerBuildingSupport.firstImageBuild()) { - LibGraalClassLoaderBase libGraalLoader = ((DuringSetupAccessImpl) access).imageClassLoader.classLoaderSupport.getLibGraalLoader(); + LibGraalLoader libGraalLoader = ((DuringSetupAccessImpl) access).imageClassLoader.classLoaderSupport.getLibGraalLoader(); if (libGraalLoader != null) { - ClassLoader libGraalClassLoader = libGraalLoader.getClassLoader(); + ClassLoader libGraalClassLoader = (ClassLoader) libGraalLoader; ClassForNameSupport.currentLayer().setLibGraalLoader(libGraalClassLoader); - - ClassLoader runtimeLibGraalClassLoader = libGraalLoader.getRuntimeClassLoader(); - if (runtimeLibGraalClassLoader != null) { - /* - * LibGraalLoader provides runtime-replacement ClassLoader instance. Make sure - * LibGraalLoader gets replaced by runtimeLibGraalClassLoader instance in image. - */ - access.registerObjectReplacer(obj -> obj == libGraalClassLoader ? runtimeLibGraalClassLoader : obj); - } } access.registerObjectReplacer(this::runtimeClassLoaderObjectReplacer); if (ImageLayerBuildingSupport.buildingInitialLayer()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/GlobalDataSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/GlobalDataSupportImpl.java new file mode 100644 index 000000000000..8a8d427789c0 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/GlobalDataSupportImpl.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted; + +import java.util.function.Supplier; + +import com.oracle.svm.core.c.GlobalLongSupplier; +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; + +import org.graalvm.nativeimage.libgraal.impl.GlobalDataSupport; + +@AutomaticallyRegisteredImageSingleton(GlobalDataSupport.class) +public final class GlobalDataSupportImpl implements GlobalDataSupport { + @Override + public Supplier createGlobal(long initialValue) { + return new GlobalLongSupplier(initialValue); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java index 0d85bde88607..d64b691325a3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java @@ -278,7 +278,16 @@ T doLookup(Class key, boolean stripRuntimeOnly, boolean allowMultiLayered checkKey(key); Object result = configObjects.get(key); if (result == null) { - throw UserError.abort("ImageSingletons do not contain key %s", key.getTypeName()); + var others = configObjects.keySet().stream()// + .filter(c -> c.getName().equals(key.getName()))// + .map(c -> c.getClassLoader().getName() + "/" + c.getTypeName())// + .toList(); + if (others.isEmpty()) { + throw UserError.abort("ImageSingletons do not contain key %s", key.getTypeName()); + } + throw UserError.abort("ImageSingletons do not contain key %s/%s but does contain the following key(s): %s", + key.getClassLoader().getName(), key.getTypeName(), + String.join(", ", others)); } else if (result == SINGLETON_INSTALLATION_FORBIDDEN) { throw UserError.abort("A LayeredImageSingleton was installed in a prior layer which forbids creating the singleton in a subsequent layer. Key %s", key.getTypeName()); } else if (result instanceof RuntimeOnlyWrapper wrapper) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index 474e1b834b20..bb3022f4bbb4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java @@ -75,6 +75,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.svm.core.SubstrateUtil; +import com.oracle.svm.util.ModuleSupport; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; @@ -82,7 +85,6 @@ import com.oracle.svm.core.NativeImageClassLoaderOptions; import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.option.AccumulatingLocatableMultiOptionValue; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.LocatableMultiOptionValue.ValueWithOrigin; @@ -97,12 +99,9 @@ import com.oracle.svm.hosted.option.HostedOptionParser; import com.oracle.svm.util.ClassUtil; import com.oracle.svm.util.LogUtils; -import com.oracle.svm.util.ModuleSupport; -import com.oracle.svm.util.ModuleSupport.Access; import com.oracle.svm.util.ReflectionUtil; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionValues; import jdk.internal.module.Modules; @@ -134,7 +133,7 @@ public final class NativeImageClassLoaderSupport { private Set javaPathsToInclude; private boolean includeAllFromClassPath; - private Optional libGraalLoader; + private Optional libGraalLoader; private List classLoaders; private final Set> classesToIncludeUnconditionally = ConcurrentHashMap.newKeySet(); @@ -232,7 +231,7 @@ public NativeImageClassLoader getClassLoader() { return classLoader; } - public LibGraalClassLoaderBase getLibGraalLoader() { + public LibGraalLoader getLibGraalLoader() { VMError.guarantee(libGraalLoader != null, "Invalid access to libGraalLoader before getting set up"); return libGraalLoader.orElse(null); } @@ -272,15 +271,15 @@ public void loadAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoa new LoadClassHandler(executor, imageClassLoader).run(); - LibGraalClassLoaderBase graalLoader = getLibGraalLoader(); - if (graalLoader != null) { - /* If we have a customLoader, register its classes to the image builder */ - for (String fqn : graalLoader.getAllClassNames()) { + LibGraalLoader loader = getLibGraalLoader(); + if (loader != null) { + /* If we have a LibGraalLoader, register its classes to the image builder */ + for (String fqn : loader.getClassModuleMap().keySet()) { try { - var clazz = graalLoader.getClassLoader().loadClass(fqn); + var clazz = ((ClassLoader) loader).loadClass(fqn); imageClassLoader.handleClass(clazz); } catch (ClassNotFoundException e) { - throw GraalError.shouldNotReachHere(e, graalLoader + " could not load class " + fqn); + throw GraalError.shouldNotReachHere(e, loader + " could not load class " + fqn); } } } @@ -573,22 +572,18 @@ private Stream processOption(OptionKey loaderClass = Class.forName(libGraalClassLoaderFQN, true, classLoader); - LibGraalClassLoaderBase loaderInstance = (LibGraalClassLoaderBase) ReflectionUtil.newInstance(loaderClass); - libGraalLoader = Optional.of(loaderInstance); - classLoaders = List.of(loaderInstance.getClassLoader(), getClassLoader()); + Class loaderClass = Class.forName(className, true, classLoader); + if (!LibGraalLoader.class.isAssignableFrom(loaderClass)) { + throw VMError.shouldNotReachHere("Class named by " + nameOption + " does not implement " + LibGraalLoader.class + '.'); + } + libGraalLoader = Optional.of((LibGraalLoader) ReflectionUtil.newInstance(loaderClass)); + classLoaders = List.of((ClassLoader) libGraalLoader.get(), getClassLoader()); } catch (ClassNotFoundException e) { - throw VMError.shouldNotReachHere("LibGraalClassLoader " + libGraalClassLoaderFQN + - " set via " + SubstrateOptionsParser.commandArgument(NativeImageOptions.LibGraalClassLoader, libGraalClassLoaderFQN) + - " could not be found.", e); - } catch (ClassCastException e) { - throw VMError.shouldNotReachHere("LibGraalClassLoader " + libGraalClassLoaderFQN + - " set via " + SubstrateOptionsParser.commandArgument(NativeImageOptions.LibGraalClassLoader, libGraalClassLoaderFQN) + - " does not extend class " + LibGraalClassLoaderBase.class.getName() + '.', e); + throw VMError.shouldNotReachHere("Class named by " + nameOption + " could not be found.", e); } } else { libGraalLoader = Optional.empty(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index cb134b30fcf1..4d46935618c4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -305,7 +305,4 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o } } }; - - @Option(help = "file:doc-files/LibGraalClassLoader.txt")// - public static final HostedOptionKey LibGraalClassLoader = new HostedOptionKey<>(""); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java index c7d20ec4d54c..86da81cdb6ad 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java @@ -209,10 +209,8 @@ private Object computeAndCacheFieldValueInterceptor(AnalysisField field) { public boolean isValueAvailable(AnalysisField field) { var interceptor = lookupFieldValueInterceptor(field); if (interceptor instanceof FieldValueTransformation transformation) { - if (transformation.getFieldValueTransformer() instanceof FieldValueTransformerWithAvailability transformerWithAvailability) { - if (!transformerWithAvailability.isAvailable()) { - return false; - } + if (!transformation.getFieldValueTransformer().isAvailable()) { + return false; } } else if (interceptor instanceof FieldValueComputer computer) { if (!computer.isAvailable()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java index 94698eb2b6c6..5367d1013d7c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java @@ -128,6 +128,7 @@ private static void initializeNativeImagePackagesAtBuildTime(ClassInitialization initializationSupport.initializeAtBuildTime("org.graalvm.collections", NATIVE_IMAGE_CLASS_REASON); initializationSupport.initializeAtBuildTime("jdk.graal.compiler", NATIVE_IMAGE_CLASS_REASON); + initializationSupport.initializeAtBuildTime("org.graalvm.nativeimage.libgraal", NATIVE_IMAGE_CLASS_REASON); initializationSupport.initializeAtBuildTime("org.graalvm.word", NATIVE_IMAGE_CLASS_REASON); initializationSupport.initializeAtBuildTime("org.graalvm.nativeimage", NATIVE_IMAGE_CLASS_REASON); initializationSupport.initializeAtBuildTime("org.graalvm.nativebridge", NATIVE_IMAGE_CLASS_REASON); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java index 19f005c69186..5f04b4e04b56 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java @@ -44,6 +44,8 @@ import java.util.function.Function; import java.util.stream.Collectors; +import jdk.graal.compiler.core.common.ContextClassLoaderScope; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import org.graalvm.collections.EconomicSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; @@ -188,8 +190,14 @@ public boolean maybeInitializeAtBuildTime(Class clazz) { * Ensure class is initialized. Report class initialization errors in a user-friendly way if * class initialization fails. */ + @SuppressWarnings("try") InitKind ensureClassInitialized(Class clazz, boolean allowErrors) { - try { + LibGraalLoader libGraalLoader = loader.classLoaderSupport.getLibGraalLoader(); + ClassLoader cl = clazz.getClassLoader(); + // Graal and JVMCI make use of ServiceLoader which uses the + // context class loader so it needs to be the libgraal loader. + ClassLoader libGraalCCL = libGraalLoader == cl ? cl : null; + try (var ignore = new ContextClassLoaderScope(libGraalCCL)) { loader.watchdog.recordActivity(); /* * This can run arbitrary user code, i.e., it can deadlock or get stuck in an endless diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/doc-files/LibGraalClassLoader.txt b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/doc-files/LibGraalClassLoader.txt deleted file mode 100644 index d843a040f927..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/doc-files/LibGraalClassLoader.txt +++ /dev/null @@ -1,12 +0,0 @@ -Specify the fully qualified class name of the LibGraalClassLoader implementation that gets used for building libgraal. - -This option is only supported for building the libgraal shared library. -The given fully qualified class name has to be a subtype of -jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase. - -When building the libgraal shared library, this option is used to specify a custom loader -the builder instantiates via default constructor, that affects image building as follows: - - 1. The custom loader is used to lookup Feature implementations passed via the --features option. - 2. All @CEntryPoint definitions from classes managed by the custom loader are processed. - 3. All @TargetClass substitutions in classes managed by the custom loader are processed. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index 5c854ef3afc1..f739362c7dcb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -44,6 +44,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.c.function.CEntryPointLiteral; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.function.CFunctionPointer; @@ -106,7 +107,6 @@ import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.Indent; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.internal.vm.annotation.Contended; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ExceptionHandler; @@ -220,7 +220,7 @@ private HostedType makeType(AnalysisType aType) { String typeName = aType.getName(); - assert GraalServices.isBuildingLibgraal() || !typeName.contains("/hotspot/") || typeName.contains("/jtt/hotspot/") || typeName.contains("/hotspot/shared/") : "HotSpot object in image " + + assert ImageInfo.inImageBuildtimeCode() || !typeName.contains("/hotspot/") || typeName.contains("/jtt/hotspot/") || typeName.contains("/hotspot/shared/") : "HotSpot object in image " + typeName; assert !typeName.contains("/analysis/meta/") : "Analysis meta object in image " + typeName; assert !typeName.contains("/hosted/meta/") : "Hosted meta object in image " + typeName; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java index de38ef8b1f5e..b6c5bdb7b5df 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java @@ -88,7 +88,6 @@ import com.oracle.svm.util.ReflectionUtil; import com.oracle.svm.util.ReflectionUtil.ReflectionUtilError; -import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -314,11 +313,6 @@ public void init(FieldValueInterceptionSupport newFieldValueInterceptionSupport) for (Class annotatedClass : annotatedClasses) { handleClass(annotatedClass); } - - List annotatedFields = imageClassLoader.findAnnotatedFields(NativeImageReinitialize.class); - for (Field annotatedField : annotatedFields) { - reinitializeField(annotatedField); - } } protected List> findTargetClasses() { @@ -330,7 +324,6 @@ protected void handleClass(Class annotatedClass) { guarantee(annotatedClass.getSuperclass() == Object.class || annotatedClass.isInterface(), "Annotated class must inherit directly from Object: %s", annotatedClass); guarantee(annotatedClass.getDeclaringClass() == null || Modifier.isStatic(annotatedClass.getModifiers()), "Annotated class must be a static inner class, or a top-level class: %s", annotatedClass); - if (!NativeImageGenerator.includedIn(ImageSingletons.lookup(Platform.class), lookupAnnotation(annotatedClass, Platforms.class))) { return; } @@ -1052,11 +1045,6 @@ private static Field getField(ResolvedJavaField annotated, Class targetClass, } } - protected void reinitializeField(Field annotatedField) { - ResolvedJavaField annotated = metaAccess.lookupJavaField(annotatedField); - fieldValueInterceptionSupport.registerFieldValueTransformer(annotated, ConstantValueFieldValueTransformer.defaultValueForField(annotated)); - } - public Class getTargetClass(Class annotatedClass) { Class annotatedBaseClass = annotatedClass; int arrayDepth = 0; diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java index 01e04f6715c9..a2f694639549 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java @@ -48,8 +48,17 @@ public final class ModuleSupport { public static final String PROPERTY_IMAGE_EXPLICITLY_LIMITED_MODULES = "svm.modulesupport.limitedModules"; public static final boolean modulePathBuild = isModulePathBuild(); - public static final Set SYSTEM_MODULES = Set.of("org.graalvm.nativeimage.builder", "org.graalvm.nativeimage", "org.graalvm.nativeimage.base", "com.oracle.svm.svm_enterprise", - "org.graalvm.word", "jdk.internal.vm.ci", "jdk.graal.compiler", "com.oracle.graal.graal_enterprise"); + public static final Set SYSTEM_MODULES = Set.of( + "com.oracle.graal.graal_enterprise", + "com.oracle.svm.svm_enterprise", + "jdk.graal.compiler", + "org.graalvm.nativeimage.libgraal", + "jdk.internal.vm.ci", + "org.graalvm.nativeimage", + "org.graalvm.nativeimage.base", + "org.graalvm.nativeimage.builder", + "org.graalvm.truffle.compiler", + "org.graalvm.word"); private ModuleSupport() { } diff --git a/truffle/mx.truffle/mx_truffle.py b/truffle/mx.truffle/mx_truffle.py index 876fca040e27..01a75a8d0748 100644 --- a/truffle/mx.truffle/mx_truffle.py +++ b/truffle/mx.truffle/mx_truffle.py @@ -680,7 +680,7 @@ def sl_jvm_gate_tests(): _sl_jvm_gate_tests(mx.get_jdk(tag='default'), force_cp=False, supports_optimization=False) _sl_jvm_gate_tests(mx.get_jdk(tag='default'), force_cp=True, supports_optimization=False) - _sl_jvm_comiler_on_upgrade_module_path_gate_tests(mx.get_jdk(tag='default')) + _sl_jvm_compiler_on_upgrade_module_path_gate_tests(mx.get_jdk(tag='default')) def _sl_jvm_gate_tests(jdk, force_cp=False, supports_optimization=True): @@ -730,7 +730,7 @@ def run_jvm_no_enterprise_jvmci_disabled(test_file): _run_sl_tests(run_jvm_no_enterprise_jvmci_disabled) -def _sl_jvm_comiler_on_upgrade_module_path_gate_tests(jdk): +def _sl_jvm_compiler_on_upgrade_module_path_gate_tests(jdk): if mx_sdk.GraalVMJDKConfig.is_graalvm(jdk.home) or mx_sdk.GraalVMJDKConfig.is_libgraal_jdk(jdk.home): # Ignore tests for Truffle LTS gate using GraalVM as a base JDK mx.log(f'Ignoring SL JVM Optimized with Compiler on Upgrade Module Path on {jdk.home} because JDK is GraalVM') @@ -739,6 +739,7 @@ def _sl_jvm_comiler_on_upgrade_module_path_gate_tests(jdk): vm_args = [ '-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI', + '-Djdk.graal.CompilationFailureAction=ExitVM', f'--upgrade-module-path={compiler.classpath_repr()}', ] diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 9f76ff7929ea..258dab8da40c 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -1368,16 +1368,12 @@ "com.oracle.truffle.libgraal.processor" : { "subDir" : "src", "sourceDirs" : ["src"], - "dependencies" : [ - "truffle:ANTLR4" - ], "requires" : [ "java.compiler", "jdk.management" ], "checkstyle" : "com.oracle.truffle.api", "javaCompliance" : "17+", - "graalCompilerSourceEdition": "ignore", }, "org.graalvm.shadowed.org.json" : { @@ -2103,7 +2099,6 @@ "maven": { "tag": ["default", "public"], }, - "graalCompilerSourceEdition": "ignore", }, "TRUFFLE_SL" : {