From 3e7e549d6c209880870e2a06c64e72e3ac7f8023 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sun, 2 Feb 2025 13:32:57 +0100 Subject: [PATCH 1/9] moved and deleted some libgraal sources --- .../loader/HostedLibGraalClassLoader.java} | 0 .../common/FeatureComponent.java} | 0 .../HotSpotGraalServiceThread.java} | 0 .../compiler/hotspot/libgraal/BuildTime.java | 227 -------- .../compiler/hotspot/libgraal/RunTime.java | 261 --------- .../hotspot/libgraal/truffle/BuildTime.java | 168 ------ .../libgraal/truffle/GraalEntryPoints.java | 198 ------- .../libgraal/truffle/HSIndirectHandle.java | 73 --- .../truffle/NativeImageHostCalls.java | 117 ---- .../libgraal/CompilerConfig.java | 0 .../compiler/libgraal}/GetCompilerConfig.java | 0 .../compiler/libgraal}/GetJNIConfig.java | 0 .../libgraal/LibGraalEntryPoints.java | 0 .../compiler}/libgraal/LibGraalFeature.java | 0 .../libgraal}/LibGraalJNIMethodScope.java | 0 .../libgraal/LibGraalNativeBridgeSupport.java | 0 .../libgraal/LibGraalSubstitutions.java | 0 .../libgraal/truffle}/FromLibGraalCalls.java | 0 .../libgraal/truffle/HSConsumer.java | 0 .../libgraal/truffle/HSTruffleCompilable.java | 0 .../truffle/HSTruffleCompilationTask.java | 0 .../truffle/HSTruffleCompilerListener.java | 0 .../truffle/HSTruffleCompilerRuntime.java | 0 .../HSTruffleSourceLanguagePosition.java | 0 .../truffle}/LibGraalObjectHandleScope.java | 0 .../truffle}/LibGraalObjectHandles.java | 0 .../LibGraalTruffleHostEnvironment.java | 0 .../LibGraalTruffleHostEnvironmentLookup.java | 0 .../truffle}/TruffleFromLibGraalCalls.java | 0 .../truffle/TruffleLibGraalShutdownHook.java | 0 .../compiler/serviceprovider/VMSupport.java | 90 --- .../libgraal/LibGraalCompilerSupport.java | 63 -- .../LibGraalFieldsOffsetsFeature.java | 481 ---------------- .../libgraal/NativeImageHostEntryPoints.java | 84 --- .../TruffleFromLibGraalStartPoints.java | 539 ------------------ 35 files changed, 2301 deletions(-) rename compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/{hotspot/libgraal/LibGraalClassLoader.java => libgraal/loader/HostedLibGraalClassLoader.java} (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot/libgraal/LibGraalClassLoaderBase.java => core/common/FeatureComponent.java} (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{core/GraalServiceThread.java => hotspot/HotSpotGraalServiceThread.java} (100%) delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/RunTime.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/BuildTime.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/GraalEntryPoints.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSIndirectHandle.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/NativeImageHostCalls.java rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/CompilerConfig.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal}/GetCompilerConfig.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal}/GetJNIConfig.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler}/libgraal/LibGraalEntryPoints.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler}/libgraal/LibGraalFeature.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal}/LibGraalJNIMethodScope.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler}/libgraal/LibGraalNativeBridgeSupport.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler}/libgraal/LibGraalSubstitutions.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle}/FromLibGraalCalls.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSConsumer.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSTruffleCompilable.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSTruffleCompilationTask.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSTruffleCompilerListener.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSTruffleCompilerRuntime.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/HSTruffleSourceLanguagePosition.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle}/LibGraalObjectHandleScope.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle}/LibGraalObjectHandles.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/LibGraalTruffleHostEnvironment.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java (100%) rename {substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal => compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle}/TruffleFromLibGraalCalls.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{hotspot => }/libgraal/truffle/TruffleLibGraalShutdownHook.java (100%) delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/VMSupport.java delete mode 100644 substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalCompilerSupport.java delete mode 100644 substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFieldsOffsetsFeature.java delete mode 100644 substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/NativeImageHostEntryPoints.java delete mode 100644 substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/TruffleFromLibGraalStartPoints.java 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 100% 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 diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoaderBase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoaderBase.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java 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 100% 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 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/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/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java similarity index 100% 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/libgraal/CompilerConfig.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetCompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetCompilerConfig.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetJNIConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/GetJNIConfig.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/LibGraalJNIMethodScope.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot/src/com/oracle/svm/graal/hotspot/LibGraalJNIMethodScope.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java 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/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java similarity index 100% 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/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalSubstitutions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java similarity index 100% rename from substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalSubstitutions.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java 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/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java similarity index 100% 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/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSConsumer.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSConsumer.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java 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/libgraal/truffle/HSTruffleCompilable.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilable.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java 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/libgraal/truffle/HSTruffleCompilationTask.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilationTask.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java 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/libgraal/truffle/HSTruffleCompilerListener.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerListener.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleCompilerRuntime.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java 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/libgraal/truffle/HSTruffleSourceLanguagePosition.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/HSTruffleSourceLanguagePosition.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java 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/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java similarity index 100% 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/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java 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/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java similarity index 100% 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/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironment.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java 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/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java similarity index 100% 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/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java 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/libgraal/truffle/TruffleLibGraalShutdownHook.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/truffle/TruffleLibGraalShutdownHook.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java 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/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/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/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()); - } -} From eea81d37dd3df3eabf47ac955ca5e134f32aee37 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sun, 2 Feb 2025 13:34:07 +0100 Subject: [PATCH 2/9] added jdk.graal.nativeimage module --- compiler/CHANGELOG.md | 6 + compiler/mx.compiler/mx_compiler.py | 8 +- compiler/mx.compiler/suite.py | 57 +- .../loader/HostedLibGraalClassLoader.java | 100 +- .../libgraal/loader/LibGraalClassLoader.java | 41 + .../core/test/CompilationWatchDogTest.java | 2 +- .../core/test/VerifyAssertionUsage.java | 18 +- .../test/VerifyLibGraalContextChecks.java | 12 +- .../compiler/core/CompilationWatchDog.java | 52 +- .../compiler/core/CompilationWrapper.java | 6 +- .../core/common/FeatureComponent.java | 34 +- .../graal/compiler/core/common/Fields.java | 78 +- .../graal/compiler/core/phases/BaseTier.java | 15 +- .../graal/compiler/debug/DebugContext.java | 11 +- .../graal/compiler/debug/IgvDumpChannel.java | 5 +- .../src/jdk/graal/compiler/graph/Edges.java | 45 + .../jdk/graal/compiler/graph/NodeClass.java | 113 ++- .../compiler/hotspot/CompilationTask.java | 19 +- .../hotspot/CompilerConfigurationFactory.java | 34 +- .../hotspot/HotSpotBackendFactory.java | 5 +- .../hotspot/HotSpotForeignCallLinkage.java | 4 +- .../hotspot/HotSpotGraalCompiler.java | 64 +- .../hotspot/HotSpotGraalCompilerFactory.java | 5 - .../HotSpotGraalJVMCIServiceLocator.java | 5 +- .../hotspot/HotSpotGraalOptionValues.java | 77 +- .../compiler/hotspot/HotSpotGraalRuntime.java | 74 +- .../hotspot/HotSpotGraalServiceThread.java | 40 +- .../graal/compiler/hotspot/HotSpotMarkId.java | 3 +- .../hotspot/HotSpotReplacementsImpl.java | 56 +- .../hotspot/HotSpotTTYStreamProvider.java | 5 +- .../compiler/hotspot/SnippetSignature.java | 3 +- .../hotspot/SymbolicSnippetEncoder.java | 14 +- .../hotspot/debug/BenchmarkCounters.java | 4 +- .../stubs/AbstractForeignCallStub.java | 4 +- .../graal/compiler/hotspot/stubs/Stub.java | 17 +- .../graal/compiler/java/BytecodeParser.java | 2 +- .../compiler/libgraal/BeforeJDK8346781.java | 43 + .../compiler/libgraal/CompilerConfig.java | 47 +- .../compiler/libgraal/GetCompilerConfig.java | 56 +- .../graal/compiler/libgraal/GetJNIConfig.java | 99 +- .../graal/compiler/libgraal/JDKLatest.java | 40 + .../libgraal/LibGraalEntryPoints.java | 921 +++--------------- .../compiler/libgraal/LibGraalFeature.java | 624 +++++------- .../libgraal/LibGraalJNIMethodScope.java | 2 +- .../libgraal/LibGraalNativeBridgeSupport.java | 18 +- .../libgraal/LibGraalSubstitutions.java | 374 +------ .../libgraal/truffle/FromLibGraalCalls.java | 100 +- .../compiler/libgraal/truffle/HSConsumer.java | 40 +- .../libgraal/truffle/HSTruffleCompilable.java | 251 ++--- .../truffle/HSTruffleCompilationTask.java | 118 +-- .../truffle/HSTruffleCompilerListener.java | 93 +- .../truffle/HSTruffleCompilerRuntime.java | 171 ++-- .../HSTruffleSourceLanguagePosition.java | 102 +- .../truffle/LibGraalObjectHandleScope.java | 4 +- .../truffle/LibGraalObjectHandles.java | 2 +- .../truffle/LibGraalTruffleEntryPoints.java | 541 ++++++++++ .../LibGraalTruffleHostEnvironment.java | 10 +- .../LibGraalTruffleHostEnvironmentLookup.java | 40 +- .../LibGraalTruffleScopeEntryPoints.java | 54 + .../truffle/TruffleFromLibGraalCalls.java | 4 +- .../truffle/TruffleLibGraalShutdownHook.java | 41 +- .../compiler/lir/phases/LIRPhaseSuite.java | 14 +- .../GeneratedInvocationPlugin.java | 9 +- .../graphbuilderconf/InvocationPlugins.java | 5 +- .../nodes/spi/SnippetParameterInfo.java | 4 - .../graal/compiler/options/OptionValues.java | 60 +- .../graal/compiler/options/OptionsParser.java | 31 +- .../nodes/IntrinsicMethodNodeInterface.java | 8 - .../serviceprovider/GlobalAtomicLong.java | 63 +- .../serviceprovider/GraalServices.java | 129 ++- .../compiler/serviceprovider/IsolateUtil.java | 14 +- .../compiler/truffle/TruffleCompilerImpl.java | 18 +- .../hotspot/HotSpotTruffleCompilerImpl.java | 7 + ...otSpotTruffleSafepointLoweringSnippet.java | 5 +- .../jdk.graal.nativeimage/snapshot.sigtest | 34 + .../jdk/graal/nativeimage/LibGraalLoader.java | 65 ++ .../graal/nativeimage/LibGraalRuntime.java | 87 ++ .../graal/nativeimage/hosted/GlobalData.java | 54 + .../nativeimage/hosted/package-info.java | 35 + .../nativeimage/impl/GlobalDataSupport.java | 32 + .../impl/LibGraalRuntimeSupport.java | 36 + .../jdk/graal/nativeimage/package-info.java | 35 + sdk/mx.sdk/mx_sdk.py | 12 +- .../org.graalvm.nativeimage/snapshot.sigtest | 1 + .../hosted/FieldValueTransformer.java | 11 +- substratevm/mx.substratevm/mx_substratevm.py | 39 +- substratevm/mx.substratevm/suite.py | 80 +- .../svm/configure/trace/AccessAdvisor.java | 1 - .../graal/GenScavengeGCFeature.java | 5 + .../oracle/svm/core/c/GlobalLongSupplier.java | 47 + ...FieldValueTransformerWithAvailability.java | 1 + .../svm/core/jdk/JVMCISubstitutions.java | 9 - .../oracle/svm/core/jdk/RuntimeSupport.java | 1 + .../libgraal/LibGraalRuntimeSupportImpl.java | 58 ++ .../oracle/svm/graal/SubstrateGraalUtils.java | 2 +- .../graal/hosted/FieldsOffsetsFeature.java | 49 +- .../graal/hosted/GraalCompilerFeature.java | 19 +- .../GraalGraphObjectReplacer.java | 7 +- .../substitutions/GraalSubstitutions.java | 68 +- .../oracle/svm/hosted/ClassLoaderFeature.java | 6 +- .../svm/hosted/GlobalDataSupportImpl.java | 40 + .../hosted/ImageSingletonsSupportImpl.java | 11 +- .../hosted/NativeImageClassLoaderSupport.java | 47 +- .../hosted/NativeImageGeneratorRunner.java | 1 + .../ameta/FieldValueInterceptionSupport.java | 6 +- .../ClassInitializationFeature.java | 1 + .../ClassInitializationSupport.java | 15 + .../hosted/doc-files/LibGraalClassLoader.txt | 12 +- .../svm/hosted/meta/UniverseBuilder.java | 4 +- .../AnnotationSubstitutionProcessor.java | 11 - .../com/oracle/svm/util/ModuleSupport.java | 13 +- truffle/mx.truffle/mx_truffle.py | 5 +- truffle/mx.truffle/suite.py | 5 - 113 files changed, 3226 insertions(+), 2939 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/JDKLatest.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java create mode 100644 compiler/src/jdk.graal.nativeimage/snapshot.sigtest create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java create mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/GlobalLongSupplier.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/GlobalDataSupportImpl.java diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index b33a9cb1e440..3fbd1502e1c0 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -2,6 +2,12 @@ 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 `jdk.graal.nativeimage` SDK module. With this module, all logic for building + libgraal has been moved into the core compiler. There is 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..31fcc2c01ab5 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -506,7 +506,12 @@ def _check_forbidden_imports(projects, package_substrings, exceptions=None): def compiler_gate_runner(suites, unit_test_runs, bootstrap_tests, tasks, extraVMarguments=None, extraUnitTestArguments=None): with Task('CheckForbiddenImports:Compiler', tasks, tags=['style']) as t: # Ensure HotSpot-independent compiler classes do not import HotSpot-specific classes - if t: _check_forbidden_imports([mx.project('jdk.graal.compiler')], ('hotspot', 'libgraal')) + if t: + exceptions = { + 'Fields.java': 'need to register libgraal feature components', + 'NodeClass.java': 'need to register libgraal feature components' + } + _check_forbidden_imports([mx.project('jdk.graal.compiler')], ('hotspot', 'libgraal'), exceptions) with Task('JDK_java_base_test', tasks, tags=['javabasetest'], report=True) as t: if t: java_base_unittest(_remove_empty_entries(extraVMarguments) + []) @@ -1485,6 +1490,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..2a18088793cf 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -164,13 +164,27 @@ # ------------- Graal ------------- + # Native Image API extensions for libgraal. + "jdk.graal.nativeimage" : { + "subDir" : "src", + "sourceDirs" : ["src"], + "dependencies" : [ + "sdk:NATIVEIMAGE" + ], + "checkstyle" : "jdk.graal.compiler", + "javaCompliance" : "21+" + }, + "jdk.graal.compiler" : { "subDir" : "src", "sourceDirs" : ["src"], "dependencies" : [ + "GRAAL_NATIVEIMAGE", + "sdk:JNIUTILS", "sdk:WORD", "sdk:COLLECTIONS", "sdk:NATIVEIMAGE", + "sdk:NATIVEBRIDGE", "truffle:TRUFFLE_COMPILER", ], "requires" : [ @@ -179,6 +193,7 @@ ], "requiresConcealed" : { "java.base" : [ + "jdk.internal.module", "jdk.internal.misc" ], "jdk.internal.vm.ci" : [ @@ -209,7 +224,8 @@ "jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider" ], "annotationProcessors" : [ - "GRAAL_PROCESSOR" + "GRAAL_PROCESSOR", + "truffle:TRUFFLE_LIBGRAAL_PROCESSOR", ], "checkPackagePrefix": "false", "checkstyleVersion" : "10.21.0", @@ -218,7 +234,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", @@ -478,7 +493,7 @@ "workingSets" : "Graal", "javaCompliance" : "21+", "dependencies" : [ - "jdk.graal.compiler", + "jdk.graal.nativeimage", ], "requiresConcealed" : { "java.base" : [ @@ -552,10 +567,43 @@ "maven": False, }, + "GRAAL_NATIVEIMAGE" : { + "subDir" : "src", + "dependencies" : [ + "jdk.graal.nativeimage", + ], + "distDependencies" : ["sdk:NATIVEIMAGE"], + "javadocType": "api", + "moduleInfo" : { + "name" : "jdk.graal.nativeimage", + "requires" : [ + "transitive org.graalvm.nativeimage", + ], + "exports" : [ + "jdk.graal.nativeimage", + "jdk.graal.nativeimage.hosted", + "jdk.graal.nativeimage.impl to org.graalvm.nativeimage.builder", + ], + "uses" : [], + "opens" : [], + }, + "description" : "Native Image API extensions for libgraal.", + "maven": { + "tag": ["default", "public"], + }, + }, + "GRAAL" : { # This distribution defines a module. "moduleInfo" : { "name" : "jdk.graal.compiler", + "requires" : [ + # These dependencies are only required when building libgraal. + # Running jargraal works without them so make them optional + # (i.e., "static") dependencies. + "static jdk.graal.nativeimage", + "static org.graalvm.nativebridge" + ], "exports" : [ """* to com.oracle.graal.graal_enterprise, org.graalvm.nativeimage.pointsto, @@ -601,9 +649,12 @@ "GRAAL_VERSION", ], "distDependencies" : [ + "GRAAL_NATIVEIMAGE", "sdk:COLLECTIONS", "sdk:WORD", "sdk:NATIVEIMAGE", + "sdk:NATIVEBRIDGE", + "sdk:JNIUTILS", "truffle:TRUFFLE_COMPILER", ], "allowsJavadocWarnings": True, diff --git a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java index aaf39c51dd3b..479b0bd64569 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.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,7 +22,15 @@ * 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 jdk.graal.nativeimage.LibGraalLoader; +import jdk.internal.jimage.BasicImageReader; +import jdk.internal.jimage.ImageLocation; +import jdk.internal.module.Modules; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -46,24 +54,17 @@ import java.util.Objects; import java.util.Set; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; - -import jdk.graal.compiler.debug.GraalError; -import jdk.internal.jimage.BasicImageReader; -import jdk.internal.jimage.ImageLocation; -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 at image build time. */ -@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"; /** * Reader for the image. @@ -75,12 +76,6 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla */ private final Map resources = new HashMap<>(); - /** - * Map from the {@linkplain Class#forName(String) name} of a class to the image path of its - * class file. - */ - private final Map classes; - /** * Map from a service name to a list of providers. */ @@ -93,12 +88,18 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla private final Map modules; /** - * Modules in which Graal classes and their dependencies are defined. + * Modules in which Graal and JVMCI classes are defined. */ private static final Set LIBGRAAL_MODULES = Set.of( "jdk.internal.vm.ci", - "org.graalvm.collections", - "org.graalvm.word", + "jdk.graal.compiler", + "org.graalvm.truffle.compiler", + "com.oracle.graal.graal_enterprise"); + + /** + * Modules containing classes that can be annotated by {@code LibGraalService}. + */ + private static final Set LIBGRAAL_SERVICES_MODULES = Set.of( "jdk.graal.compiler", "org.graalvm.truffle.compiler", "com.oracle.graal.graal_enterprise"); @@ -107,11 +108,16 @@ final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalCla ClassLoader.registerAsParallelCapable(); } - public final Path libGraalJavaHome; + private final Path libgraalJavaHome = Path.of(System.getProperty(LIBGRAAL_JAVA_HOME_PROPERTY_NAME, System.getProperty("java.home"))); + @Override + public Path getJavaHome() { + return libgraalJavaHome; + } + + @SuppressWarnings("unused") public HostedLibGraalClassLoader() { super(LibGraalClassLoader.LOADER_NAME, Feature.class.getClassLoader()); - libGraalJavaHome = Path.of(JAVA_HOME_PROPERTY_VALUE); try { /* @@ -129,9 +135,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 = libgraalJavaHome.resolve(Path.of("lib", "modules")); this.imageReader = BasicImageReader.open(imagePath); for (var entry : imageReader.getEntryNames()) { int secondSlash = entry.indexOf('/', 1); @@ -148,7 +153,6 @@ public HostedLibGraalClassLoader() { services.computeIfAbsent(p.service(), k -> new ArrayList<>()).addAll(p.providers()); } } else { - classesMap.put(className, entry); modulesMap.put(className, module); } } @@ -157,28 +161,29 @@ public HostedLibGraalClassLoader() { } 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 getModuleMap() { return modules; } - /* Allow image builder to perform registration action on each class this loader provides. */ - @Override - public Set getAllClassNames() { - return classes.keySet(); + public Set getServicesModules() { + return LIBGRAAL_SERVICES_MODULES; } @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)) { @@ -261,7 +266,7 @@ 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 @@ -318,22 +323,7 @@ public String getContentType() { } @Override - public HostedLibGraalClassLoader getClassLoader() { - return this; - } - - @Override - public LibGraalClassLoader getRuntimeClassLoader() { + public ClassLoader 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.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java new file mode 100644 index 000000000000..90df8b485bbe --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java @@ -0,0 +1,41 @@ +/* + * 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.loader; + +import org.graalvm.nativeimage.hosted.Feature.DuringSetupAccess; + +/** + * The image runtime class loader that {@linkplain DuringSetupAccess#registerObjectReplacer + * replaces} the build-time instance of {@link HostedLibGraalClassLoader}. + */ +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.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/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/FeatureComponent.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java index 0fb49d052f7d..0a2ac2ae1310 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java @@ -22,33 +22,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.graal.compiler.core.common; -package jdk.graal.compiler.hotspot.libgraal; +import org.graalvm.nativeimage.hosted.Feature; -import java.util.Map; -import java.util.Set; - -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(); - - /** - * Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the - * name of its enclosing module. - */ - Map getModules(); +/** + * Implemented by classes that have logic specific to a {@link Feature}s. + */ +public interface FeatureComponent { /** - * Get unmodifiable set of fully qualified names of all classes this loader can load. + * Called during analysis of {@code feature}. + * + * @see Feature#duringAnalysis(Feature.DuringAnalysisAccess) */ - Set getAllClassNames(); + void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access); } 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..95b443d4c97b 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 @@ -24,18 +24,25 @@ */ 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 jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.Edges; +import jdk.graal.compiler.libgraal.LibGraalFeature; import jdk.internal.misc.Unsafe; +import org.graalvm.nativeimage.ImageInfo; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.Feature.BeforeCompilationAccess; /** * Describes fields in a class, primarily for access via {@link Unsafe}. */ -public class Fields { +public class Fields implements FeatureComponent { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final Fields EMPTY_FIELDS = new Fields(Collections.emptyList()); @@ -57,6 +64,7 @@ public class Fields { private final Class[] declaringClasses; + @SuppressWarnings("this-escape") protected Fields(List fields) { Collections.sort(fields); this.offsets = new long[fields.size()]; @@ -71,10 +79,51 @@ protected Fields(List fields) { declaringClasses[index] = f.declaringClass; index++; } + + if (ImageInfo.inImageBuildtimeCode() && LibGraalFeature.singleton() != null) { + LibGraalFeature.singleton().addFeatureComponent(this); + } + } + + private 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 access provides the new offsets via {@link BeforeCompilationAccess#objectFieldOffset} + * @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(Feature.BeforeCompilationAccess access) { + long[] newOffsets = new long[offsets.length]; + for (int i = 0; i < offsets.length; i++) { + Field field = getField(i); + long newOffset = access.objectFieldOffset(field); + newOffsets[i] = newOffset; + } + return Map.entry(newOffsets, 0L); + } + + @Override + public void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access) { + if (feature == LibGraalFeature.singleton()) { + for (int i = 0; i < offsets.length; i++) { + Field field = getField(i); + access.registerAsUnsafeAccessed(field); + } + } } public static Fields create(ArrayList fields) { - if (fields.size() == 0) { + if (fields.isEmpty()) { return EMPTY_FIELDS; } return new Fields(fields); @@ -93,15 +142,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/phases/BaseTier.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/BaseTier.java index ce1fb43aaff8..5bf50c3c9697 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 @@ -34,6 +34,7 @@ import jdk.graal.compiler.phases.BasePhase; import jdk.graal.compiler.phases.PhaseSuite; import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.nativeimage.LibGraalRuntime; public class BaseTier extends PhaseSuite { @@ -50,10 +51,16 @@ 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(); + if (GraalServices.isInLibgraal()) { + /* + * 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())) { + LibGraalRuntime.notifyLowMemoryPoint(false); + LibGraalRuntime.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/IgvDumpChannel.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java index 08f5c1a71eac..8dd00142c345 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,7 +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 +92,7 @@ void realClose() throws IOException { } } - @NativeImageReinitialize private static boolean networkDumpingUnsupportedWarned; + private static boolean networkDumpingUnsupportedWarned; WritableByteChannel channel() throws IOException { if (closed) { @@ -147,7 +146,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..0553d368f2ad 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 @@ -29,11 +29,15 @@ import java.util.ArrayList; import java.util.Iterator; +import java.util.Map; 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; +import org.graalvm.nativeimage.hosted.Feature; /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the @@ -41,8 +45,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 +84,21 @@ public enum Type { private final int directCount; private final Type type; + private final long iterationMask; + @SuppressWarnings("this-escape") public Edges(Type type, int directCount, ArrayList edges) { super(edges); this.type = type; this.directCount = directCount; + this.iterationMask = computeIterationMask(type, directCount, getOffsets()); + } + + @Override + public Map.Entry recomputeOffsetsAndIterationMask(Feature.BeforeCompilationAccess access) { + Map.Entry e = super.recomputeOffsetsAndIterationMask(access); + 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..983a60254ca8 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; @@ -44,6 +47,9 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.core.common.FeatureComponent; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; @@ -71,8 +77,10 @@ import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodeinfo.Verbosity; import jdk.internal.misc.Unsafe; +import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; /** * Metadata for every {@link Node} type. The metadata includes: @@ -82,7 +90,7 @@ *
  • The identifier for an {@link IterableNodeType} class.
  • *
*/ -public final class NodeClass extends FieldIntrospection { +public final class NodeClass extends FieldIntrospection implements FeatureComponent { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); // Timers for creation of a NodeClass instance @@ -94,11 +102,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 +163,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 +201,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 +219,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()) { @@ -285,6 +285,13 @@ private NodeClass(Class clazz, NodeClass superNodeClass, FieldsSca debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); } assert verifyMemoryEdgeInvariant(fs) : "Nodes participating in the memory graph should have at most 1 optional memory input."; + + if (ImageInfo.inImageBuildtimeCode() && LibGraalFeature.singleton() != null) { + LibGraalFeature.singleton().addFeatureComponent(this); + } + + // All NodeClass instances must be constructed at libgraal build time + GraalError.guarantee(!GraalServices.isInLibgraal(), getClazz().getName()); } private static boolean verifyMemoryEdgeInvariant(NodeFieldsScanner fs) { @@ -308,27 +315,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 +340,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 @@ -419,10 +405,20 @@ public EnumSet getAllowedUsageTypes() { return allowedUsageTypes; } + @Override + public void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access) { + if (feature == LibGraalFeature.singleton()) { + if (!Modifier.isAbstract(getClazz().getModifiers())) { + /* Support for NodeClass.allocateInstance. */ + access.registerAsUnsafeAllocated(getClazz()); + } + } + } + /** * 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 +1071,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 +1142,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 +1176,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 +1210,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 +1241,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 +1269,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 +1313,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 +1343,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 +1382,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 +1395,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 +1422,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 +1453,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..216311bb7e67 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 @@ -35,6 +35,8 @@ import java.io.PrintStream; +import jdk.graal.compiler.options.Option; +import jdk.graal.nativeimage.LibGraalRuntime; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -58,9 +60,7 @@ 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; @@ -80,9 +80,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." + @@ -492,11 +489,13 @@ 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())); + if (GraalServices.isInLibgraal()) { + // Notify the runtime that most objects allocated in the current compilation + // are dead and can be reclaimed. + try (DebugCloseable timer = HintedFullGC.start(debug)) { + LibGraalRuntime.notifyLowMemoryPoint(true); + LibGraalRuntime.processReferences(); + } } return result; } 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..20877b77eb81 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.libgraal.LibGraalFeature.NATIVE_IMAGE_SETTING_KEY_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(NATIVE_IMAGE_SETTING_KEY_PREFIX))// + .map(e -> { + String key = e.getKey().toString().substring(NATIVE_IMAGE_SETTING_KEY_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..83088874ec8f 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,6 +30,7 @@ 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; @@ -46,6 +47,7 @@ import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.phases.OnStackReplacementPhase; import jdk.graal.compiler.java.GraphBuilderPhase; +import jdk.graal.compiler.libgraal.LibGraalJNIMethodScope; import jdk.graal.compiler.lir.asm.CompilationResultBuilderFactory; import jdk.graal.compiler.lir.phases.LIRSuites; import jdk.graal.compiler.nodes.Cancellable; @@ -63,7 +65,8 @@ 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.graal.compiler.word.Word; +import jdk.graal.nativeimage.LibGraalRuntime; import jdk.internal.misc.Unsafe; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; @@ -77,6 +80,8 @@ import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; import jdk.vm.ci.runtime.JVMCICompiler; +import org.graalvm.jniutils.JNI; +import org.graalvm.jniutils.JNIMethodScope; import org.graalvm.nativeimage.ImageInfo; public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable, JVMCICompilerShadow, GraalCompiler.RequestedCrashHandler { @@ -125,12 +130,52 @@ public HotSpotGraalRuntimeProvider getGraalRuntime() { return graalRuntime; } + /** + * 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(HotSpotGraalRuntime.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. + */ + HotSpotGraalRuntime.doReferenceHandling(); + } + } + } + @SuppressWarnings("try") @Override public CompilationRequestResult compileMethod(CompilationRequest request) { - try (AutoCloseable ignored = VMSupport.getCompilationRequestScope()) { + try (AutoCloseable ignored = ImageInfo.inImageRuntimeCode() ? new LibGraalCompilationRequestScope() : null) { return compileMethod(request, true, getGraalRuntime().getOptions()); } catch (Exception e) { + e.printStackTrace(System.out); return HotSpotCompilationRequestResult.failure(e.toString(), false); } } @@ -139,7 +184,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(); @@ -163,7 +208,8 @@ public CompilationRequestResult compileMethod(CompilationRequest request, boolea boolean oneIsolatePerCompilation = ImageInfo.inImageRuntimeCode() && 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 = ImageInfo.inImageRuntimeCode() ? 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,7 +414,7 @@ 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) { @@ -386,7 +432,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 + } + LibGraalRuntime.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..1da599ea8cfd 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,7 +27,8 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.io.PrintStream; -import java.util.HashMap; +import java.util.Comparator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -41,7 +42,10 @@ import jdk.graal.compiler.options.OptionsParser; import jdk.vm.ci.common.InitTimer; -import jdk.vm.ci.common.NativeImageReinitialize; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.MapCursor; +import org.graalvm.nativeimage.ImageInfo; +import org.graalvm.nativeimage.RuntimeOptions; /** * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The @@ -73,7 +77,7 @@ public class HotSpotGraalOptionValues { /** * 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 +86,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 +116,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(); @@ -168,14 +171,42 @@ private static String stripPrefix(String name, String prefix) { } /** - * Substituted by {@code Target_jdk_graal_compiler_hotspot_HotSpotGraalOptionValues}. - * * @param settings unparsed libgraal option values */ - 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())); + private static void notifyLibgraalOptions(EconomicMap settings) { + if (ImageInfo.inImageRuntimeCode()) { + 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); + } + } + } else { + System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", settings.toString()); + } } + /** + * The set of libgraal options seen on the command line. + */ + static EconomicSet explicitOptions = EconomicSet.create(); + private static OptionValues initializeOptions() { EconomicMap, Object> values = parseOptions(); OptionValues options = new OptionValues(values); @@ -188,17 +219,21 @@ 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); + if (all && ImageInfo.inImageRuntimeCode()) { + if (ImageInfo.inImageRuntimeCode()) { + Comparator comparator = Comparator.comparing(RuntimeOptions.Descriptor::name); + RuntimeOptions.listDescriptors().stream().sorted(comparator).forEach(d -> { + String assign = explicitOptions.contains(d.name()) ? ":=" : "="; + OptionValues.printHelp(out, LIBGRAAL_VM_OPTION_PROPERTY_PREFIX, + d.name(), + RuntimeOptions.get(d.name()), + d.valueType(), + assign, + "[community edition]", + d.help(), + List.of()); + }); + } } } - - /** - * 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..11052d7c19c3 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,6 +35,15 @@ import java.util.Map; import java.util.function.Predicate; +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.TargetClass; +import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.word.Word; +import jdk.graal.nativeimage.LibGraalRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import org.graalvm.jniutils.JNI; +import org.graalvm.jniutils.JNIExceptionWrapper; +import org.graalvm.jniutils.JNIUtil; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; @@ -67,7 +76,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; @@ -76,6 +84,8 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.runtime.JVMCIBackend; +import org.graalvm.nativeimage.StackValue; +import org.graalvm.nativeimage.VMRuntime; //JaCoCo Exclude @@ -100,6 +110,31 @@ private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAcc private final String compilerConfigurationName; private final HotSpotBackend hostBackend; + /** + * 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. + */ + Target_jdk_vm_ci_hotspot_Cleaner.clean(); + } + + @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(); + } + public GlobalMetrics getMetricValues() { return metricValues; } @@ -194,7 +229,9 @@ public GlobalMetrics getMetricValues() { this.compilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); - VMSupport.startupLibGraal(); + if (ImageInfo.inImageRuntimeCode()) { + VMRuntime.initialize(); + } } /** @@ -429,12 +466,41 @@ synchronized void shutdown() { } String cbClassName = callback.substring(0, lastDot); String cbMethodName = callback.substring(lastDot + 1); - VMSupport.invokeShutdownCallback(cbClassName, cbMethodName); + + JNI.JNIEnv env = Word.unsigned(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); + } - VMSupport.shutdownLibGraal(); + VMRuntime.shutdown(); } } + 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; + } + void clearMetrics() { metricValues.clear(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java b/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/hotspot/HotSpotGraalServiceThread.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/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/libgraal/BeforeJDK8346781.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java new file mode 100644 index 000000000000..20a417c2431d --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java @@ -0,0 +1,43 @@ +/* + * 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 java.util.stream.Stream; + +import jdk.vm.ci.services.Services; + +/** + * Determines if the JDK runtime does not include JDK-8346781. + */ +public class BeforeJDK8346781 implements BooleanSupplier { + + static final boolean VALUE = Stream.of(Services.class.getFields()).anyMatch(f -> f.getName().equals("IS_BUILDING_NATIVE_IMAGE")); + + @Override + public boolean getAsBoolean() { + return VALUE; + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java index 70bae2af222e..168a093c8302 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/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.libgraal; +import java.io.FileOutputStream; +import java.io.PrintStream; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Path; @@ -49,6 +51,8 @@ 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 +65,7 @@ * {@link jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.Stubs#initStubs} * */ +@Platforms(Platform.HOSTED_ONLY.class) public class CompilerConfig { /** @@ -74,7 +79,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 +87,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 +109,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/libgraal/GetCompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java index ad11fc4f03d3..ede2b814f431 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/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,20 @@ 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.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 +95,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 +115,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 +158,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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java index 92178a4c508a..7c36396663e0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java +++ b/compiler/src/jdk.graal.compiler/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. */ @@ -83,7 +80,7 @@ public final class GetJNIConfig implements AutoCloseable { private GetJNIConfig(ClassLoader loader) { this.loader = loader; - Path javaExe = getJavaExe(Path.of(System.getProperty("java.home"))); + Path javaExe = getJavaExe(Path.of(GraalServices.getSavedProperty("java.home"))); 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); } @@ -178,9 +197,6 @@ private UserError.UserException error(String format, Object... args) { */ @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)) { Map> classes = new HashMap<>(); for (String line : source.lines) { @@ -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/src/jdk/graal/compiler/libgraal/JDKLatest.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/JDKLatest.java new file mode 100644 index 000000000000..cef8bbe6a07e --- /dev/null +++ b/compiler/src/jdk.graal.compiler/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/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java index 6f8704ffd352..024734a69312 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.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,181 +22,96 @@ * 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.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 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.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; +import static jdk.graal.compiler.serviceprovider.GraalServices.getCurrentThreadAllocatedBytes; +import static jdk.graal.compiler.serviceprovider.GraalServices.isThreadAllocatedMemorySupported; + /** - * 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. + * Encapsulates {@link CEntryPoint} implementations. */ 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"); + private LibGraalEntryPoints() { } - /** - * 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); - } - } + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - /** - * 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); - } + private record CachedOptions(OptionValues options, long hash) { } - /** - * 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); - } - } + private static final ThreadLocal CACHED_OPTIONS_THREAD_LOCAL = new ThreadLocal<>(); - /** - * 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); - } - } + 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); + } - /** - * 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); + 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}. - * 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 @@ -213,7 +128,7 @@ static void ttyPrintf(String format, Object... args) { * @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;
@@ -248,30 +163,45 @@ private static long compileMethod(JNIEnv jniEnv,
                     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;
+            HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+            HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
+            if (methodHandle == 0L) {
+                return 0L;
             }
-            BiConsumer timeAndMemConsumer;
-            Supplier currentThreadAllocatedBytes;
-            if (timeAndMemBufferAddress != 0) {
-                timeAndMemConsumer = (timeSpent, bytesAllocated) -> {
+
+            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);
-                };
-                ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
-                currentThreadAllocatedBytes = () -> threadMXBean.getCurrentThreadAllocatedBytes();
-            } else {
-                timeAndMemConsumer = null;
-                currentThreadAllocatedBytes = null;
+                }
+                HotSpotInstalledCode installedCode = task.getInstalledCode();
+                if (printMetrics) {
+                    GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues();
+                    metricValues.print(options);
+                    metricValues.clear();
+                }
+                return runtime.translate(installedCode);
             }
-
-            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));
@@ -285,7 +215,7 @@ private static long compileMethod(JNIEnv jniEnv,
              * libgraal doesn't use a dedicated reference handler thread, so we trigger the
              * reference handling manually when a compilation finishes.
              */
-            doReferenceHandling();
+            HotSpotGraalRuntime.doReferenceHandling();
         }
     }
 
@@ -300,634 +230,57 @@ private static long hashConstantOopFields(JNIEnv jniEnv,
                     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]));
+            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();
+                                }
+                            }
+                        }
+                    }
                 }
-                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]));
+                if (!useScope) {
+                    System.gc();
+                    if (verbose) {
+                        System.out.println("calling reference handling");
+                    }
+                    HotSpotGraalRuntime.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);
                 }
-                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);
+            return hash;
         } catch (Throwable t) {
-            JNIExceptionWrapper.throwInHotSpot(env, t);
+            JNIExceptionWrapper.throwInHotSpot(jniEnv, 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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java
index 6e80301d3a26..0e95d5baa57a 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.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,507 +22,361 @@
  * 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 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.lang.module.ModuleDescriptor;
+import java.lang.reflect.Field;
 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 java.util.function.Function;
-import java.util.regex.Pattern;
 
+import jdk.graal.compiler.core.common.spi.ForeignCallSignature;
+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.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.services.JVMCIServiceLocator;
 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 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.core.common.Fields;
+import jdk.graal.compiler.debug.GraalError;
+import jdk.graal.compiler.graph.Edges;
 import jdk.graal.compiler.options.OptionDescriptor;
 import jdk.graal.compiler.options.OptionKey;
-import jdk.graal.compiler.serviceprovider.LibGraalService;
-import jdk.vm.ci.code.TargetDescription;
+import jdk.graal.compiler.core.common.FeatureComponent;
+import jdk.graal.nativeimage.LibGraalLoader;
+import jdk.vm.ci.hotspot.HotSpotModifiers;
+import org.graalvm.nativeimage.hosted.RuntimeSystemProperties;
 
 /**
  * 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. + * Prefix to be used when {@linkplain RuntimeSystemProperties#register registering} properties + * describing the image configuration for libgraal. This is analogous to the configuration info + * displayed by {@code -XshowSettings}. + * + * For example: + * + *
+     * RuntimeSystemProperties.register(NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", "serial");
+     * 
*/ - Class buildTimeClass; + public static final String NATIVE_IMAGE_SETTING_KEY_PREFIX = "org.graalvm.nativeimage.setting."; - /** - * Handle to {@link jdk.graal.compiler.phases.BasePhase} in the guest. - */ - private Class basePhaseClass; + private static LibGraalFeature singleton; - private Function, Object> newBasePhaseStatistics; + public LibGraalFeature() { + synchronized (LibGraalFeature.class) { + GraalError.guarantee(singleton == null, "only a single %s instance should be created", LibGraalFeature.class.getName()); + singleton = this; + } + } /** - * Handle to {@link jdk.graal.compiler.lir.phases.LIRPhase} in the guest. + * @return the singleton {@link LibGraalFeature} instance if called within the context of the + * class loader used to load the code being compiled into the libgraal image, otherwise + * null */ - private Class lirPhaseClass; - - private Function, Object> newLIRPhaseStatistics; - - MethodHandle handleGlobalAtomicLongGetInitialValue; - - public ClassLoader getLoader() { - return loader; + public static LibGraalFeature singleton() { + // Cannot use ImageSingletons here as it is not initialized early enough. + return singleton; } - 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) { + /** + * Looks up a class in the libgraal class loader. + * + * @throws Error if the lookup fails + */ + public static Class lookupClass(String className) { try { - return loader.loadClass(name); - } catch (ClassNotFoundException e) { - throw new AssertionError("%s unable to load class '%s'".formatted(loader.getName(), name)); + return Class.forName(className, false, LibGraalFeature.class.getClassLoader()); + } catch (ClassNotFoundException ex) { + throw new GraalError(ex); } } /** - * 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}.
  • - *
+ * Looks up a field via reflection and makes it accessible for reading. + * + * @throws Error if the operation fails */ - @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); - + public static Field lookupField(Class declaringClass, String fieldName) { 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); + Field result = declaringClass.getDeclaredField(fieldName); + Modules.addOpensToAllUnnamed(declaringClass.getModule(), declaringClass.getPackageName()); + result.setAccessible(true); + return result; + } catch (ReflectiveOperationException ex) { + throw new GraalError(ex); } } - @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)); + public static final class IsEnabled implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + Class clazz = LibGraalFeature.class; + return ImageSingletons.contains(clazz); } } - static Module getBootModule(String moduleName) { - return ModuleLayer.boot().findModule(moduleName).orElseThrow(); + final LibGraalLoader libgraalLoader = (LibGraalLoader) getClass().getClassLoader(); + + /** + * Set of {@link FeatureComponent}s created during analysis. + */ + private final Set libGraalFeatureComponents = ConcurrentHashMap.newKeySet(); + + public void addFeatureComponent(FeatureComponent fc) { + libGraalFeatureComponents.add(fc); } @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); + public void afterRegistration(AfterRegistrationAccess access) { + ImageSingletons.add(NativeBridgeSupport.class, new LibGraalNativeBridgeSupport()); - 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); + // The qualified exports from java.base to jdk.internal.vm.ci + // and jdk.graal.compiler need to be expressed as exports to + // ALL-UNNAMED so that access is also possible when these classes + // are loaded via the libgraal loader. + Module javaBase = ModuleLayer.boot().findModule("java.base").orElseThrow(); + Set exports = javaBase.getDescriptor().exports(); + for (ModuleDescriptor.Exports e : exports) { + if (e.targets().contains("jdk.internal.vm.ci") || e.targets().contains("jdk.graal.compiler")) { + Modules.addExportsToAllUnnamed(javaBase, e.source()); + } } + } - DuringSetupAccessImpl accessImpl = (DuringSetupAccessImpl) access; - accessImpl.registerClassReachabilityListener(this::registerPhaseStatistics); - optionCollector = new OptionCollector(LibGraalEntryPoints.vmOptionDescriptors); + @Override + public void duringSetup(DuringSetupAccess access) { + optionCollector = new OptionCollector(); access.registerObjectReachabilityHandler(optionCollector::accept, OptionKey.class); - access.registerObjectReachabilityHandler(optionCollector::accept, loadClassOrFail(OptionKey.class.getName())); - GetJNIConfig.register(loader); + GetJNIConfig.register((ClassLoader) libgraalLoader); } 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}. + * Collects all instances of the LibGraalLoader loaded {@link OptionKey} class reached by the + * static analysis. */ - 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 final class OptionCollector implements Consumer> { + private final Set> options = Collections.newSetFromMap(new ConcurrentHashMap<>()); 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) { + public void accept(OptionKey option) { if (sealed) { - VMError.guarantee(options.contains(option), "All options must have been discovered during static analysis: %s", option); + GraalError.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); + Map modules = libgraalLoader.getModuleMap(); + 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); } - } 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 BeforeCompilationAccess beforeCompilationAccess; + + /** + * 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"); } - } - private void registerPhaseStatistics(DuringAnalysisAccess a, Class newlyReachableClass) { - DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a; + void register(BeforeAnalysisAccess access) { + access.registerFieldValueTransformer(fieldsOffsetsField, this); + access.registerFieldValueTransformer(edgesIterationMaskField, this); + } - if (!Modifier.isAbstract(newlyReachableClass.getModifiers())) { - boolean requireAnalysisIteration = true; - if (basePhaseClass.isAssignableFrom(newlyReachableClass)) { - LibGraalCompilerSupport.registerStatistics(newlyReachableClass, LibGraalCompilerSupport.get().basePhaseStatistics, - newBasePhaseStatistics.apply(newlyReachableClass)); + @Override + public boolean isAvailable() { + return beforeCompilationAccess != null; + } - } else if (lirPhaseClass.isAssignableFrom(newlyReachableClass)) { - LibGraalCompilerSupport.registerStatistics(newlyReachableClass, LibGraalCompilerSupport.get().lirPhaseStatistics, - newLIRPhaseStatistics.apply(newlyReachableClass)); - } else { - requireAnalysisIteration = false; + @Override + public Object transform(Object receiver, Object originalValue) { + Map.Entry repl = getReplacement(receiver); + if (originalValue instanceof long[]) { + return repl.getKey(); } + return repl.getValue(); + } - if (requireAnalysisIteration) { - access.requireAnalysisIteration(); + 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); + } } + @SuppressWarnings("unchecked") @Override - public void beforeAnalysis(BeforeAnalysisAccess baa) { - BeforeAnalysisAccessImpl impl = (BeforeAnalysisAccessImpl) baa; - var bb = impl.getBigBang(); + public void beforeAnalysis(BeforeAnalysisAccess access) { + + new FieldOffsetsTransformer().register(access); /* 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")); + 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(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Character$CharacterCache"), "cache")); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Character$CharacterCache"), "cache")); RuntimeReflection.registerAllDeclaredClasses(Byte.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Byte$ByteCache"), "cache")); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Byte$ByteCache"), "cache")); RuntimeReflection.registerAllDeclaredClasses(Short.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Short$ShortCache"), "cache")); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Short$ShortCache"), "cache")); RuntimeReflection.registerAllDeclaredClasses(Integer.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Integer$IntegerCache"), "cache")); + RuntimeReflection.register(lookupField(lookupClass("java.lang.Integer$IntegerCache"), "cache")); RuntimeReflection.registerAllDeclaredClasses(Long.class); - RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Long$LongCache"), "cache")); + RuntimeReflection.register(lookupField(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); - } - } + doLegacyJVMCIInitialization(); - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, buildTimeClass, false, "org.graalvm.word", "org.graalvm.word.impl"); + Path libGraalJavaHome = libgraalLoader.getJavaHome(); + 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); + } + } - configureGraalForLibGraal.invoke(arch, - guestServiceClasses, - registerAsInHeap, - nativeImageLocationQualifier, - configResult.encodedConfig()); + EconomicMap libgraalObjects = (EconomicMap) ObjectCopier.decode(configResult.encodedConfig(), (ClassLoader) libgraalLoader); + EncodedSnippets encodedSnippets = (EncodedSnippets) libgraalObjects.get("encodedSnippets"); - initGraalRuntimeHandles(mhl.findStatic(buildTimeClass, "getRuntimeHandles", methodType(Map.class))); - initializeTruffle(); - } catch (Throwable e) { - throw VMError.shouldNotReachHere(e); + // 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()); } - @SuppressWarnings("unchecked") - private static void initGraalRuntimeHandles(MethodHandle getRuntimeHandles) throws Throwable { - ImageSingletons.add(LibGraalEntryPoints.class, new LibGraalEntryPoints((Map) getRuntimeHandles.invoke())); + /** + * 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); + } } - @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(); + @Override + public void duringAnalysis(DuringAnalysisAccess access) { + for (var c : libGraalFeatureComponents) { + c.duringAnalysis(this, access); + } } - @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))); + @Override + public void beforeCompilation(BeforeCompilationAccess access) { + beforeCompilationAccess = access; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java index 7b9271205fa7..47ad9f5fd524 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java +++ b/compiler/src/jdk.graal.compiler/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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java index b1167d39a63a..70bc289a54dd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java +++ b/compiler/src/jdk.graal.compiler/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/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java index 14b29ffd7afd..a3296a3ec36e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.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,50 +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.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 { +class LibGraalSubstitutions { - @TargetClass(className = "jdk.vm.ci.services.Services", classLoader = LibGraalClassLoaderSupplier.class, onlyWith = LibGraalFeature.IsEnabled.class) + @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. @@ -73,6 +39,7 @@ static final class Target_jdk_vm_ci_services_Services { // Checkstyle: stop @Alias // @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias, isFinal = true)// + @TargetElement(onlyWith = BeforeJDK8346781.class)// public static boolean IS_BUILDING_NATIVE_IMAGE = false; // Checkstyle: resume @@ -86,336 +53,5 @@ static final class Target_jdk_vm_ci_services_Services { @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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java index d774f3286525..9bc78ad4a1fb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java +++ b/compiler/src/jdk.graal.compiler/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/libgraal/truffle/HSConsumer.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java index 29237f692c0d..9ae2c92528cc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java +++ b/compiler/src/jdk.graal.compiler/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/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java index c9923862d9da..891e6a9d297c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java @@ -22,27 +22,57 @@ * 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; +package jdk.graal.compiler.libgraal.truffle; import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; - +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 HSIndirectHandle implements TruffleCompilable { +final class HSTruffleCompilable extends HSObject implements TruffleCompilable { - private static final Handles HANDLES = new Handles(); + private static volatile JNIMethod prepareForCompilationNewMethod; + private static volatile JNIMethod onCompilationSuccessMethod; + private final TruffleFromLibGraalCalls calls; /** * Handle to {@code speculationLog} field of the {@code OptimizedCallTarget}. */ @@ -50,85 +80,125 @@ final class HSTruffleCompilable extends HSIndirectHandle implements TruffleCompi private volatile String cachedName; private volatile String cachedString; - HSTruffleCompilable(Object hsHandle) { - super(hsHandle); + 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) { - try { - res = (long) HANDLES.getFailedSpeculationsAddress.invoke(hsHandle); - cachedFailedSpeculationsAddress = res; - } catch (Throwable t) { - throw handleException(t); - } + res = HSTruffleCompilableGen.callGetFailedSpeculationsAddress(calls, env(), getHandle()); + cachedFailedSpeculationsAddress = res; } return HotSpotGraalServices.newHotSpotSpeculationLog(cachedFailedSpeculationsAddress); } + @TruffleFromLibGraal(GetCompilerOptions) @Override - @SuppressWarnings("unchecked") public Map getCompilerOptions() { - try { - return (Map) HANDLES.getCompilerOptions.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); + 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() { - try { - return (long) HANDLES.engineId.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilableGen.callEngineId(calls, env(), getHandle()); } + @TruffleFromLibGraal(PrepareForCompilation) @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); + 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() { - try { - return (boolean) HANDLES.isTrivial.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilableGen.callIsTrivial(calls, env(), getHandle()); } + @TruffleFromLibGraal(AsJavaConstant) @Override public JavaConstant asJavaConstant() { - long constantHandle; - try { - constantHandle = (long) HANDLES.asJavaConstant.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + 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 { - Object serializedExceptionHsHandle = HANDLES.createStringSupplier.invoke(serializedException); - HANDLES.onCompilationFailed.invoke(hsHandle, serializedExceptionHsHandle, suppressed, bailout, permanentBailout, graphTooBig); - } catch (Throwable t) { - throw handleException(t); + 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) { - NativeImageHostCalls.onCompilationSuccess(hsHandle, compilationTier, 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 @@ -136,104 +206,65 @@ public boolean onInvalidate(Object source, CharSequence reason, boolean wasActiv throw GraalError.shouldNotReachHere("Should not be reachable."); // ExcludeFromJacocoGeneratedReport } + @TruffleFromLibGraal(GetCompilableName) @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); - } + 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) { - try { - res = (String) HANDLES.compilableToString.invoke(hsHandle); - cachedString = res; - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = JNIMethodScope.env(); + res = createString(env, HSTruffleCompilableGen.callCompilableToString(calls, env, getHandle())); + cachedString = res; } return res; } + @TruffleFromLibGraal(GetNonTrivialNodeCount) @Override public int getNonTrivialNodeCount() { - try { - return (int) HANDLES.getNonTrivialNodeCount.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilableGen.callGetNonTrivialNodeCount(calls, env(), getHandle()); } + @TruffleFromLibGraal(CountDirectCallNodes) @Override public int countDirectCallNodes() { - try { - return (int) HANDLES.countDirectCallNodes.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilableGen.callCountDirectCallNodes(calls, env(), getHandle()); } + @TruffleFromLibGraal(GetCompilableCallCount) @Override public int getCallCount() { - try { - return (int) HANDLES.getCompilableCallCount.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilableGen.callGetCompilableCallCount(calls, env(), getHandle()); } + @TruffleFromLibGraal(CancelCompilation) @Override public boolean cancelCompilation(CharSequence reason) { - try { - return (boolean) HANDLES.cancelCompilation.invoke(hsHandle, reason); - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = env(); + return HSTruffleCompilableGen.callCancelCompilation(calls, env, getHandle(), JNIUtil.createHSString(env, reason.toString())); } + @TruffleFromLibGraal(IsSameOrSplit) @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); - } + JObject astHandle = ast == null ? WordFactory.nullPointer() : ((HSTruffleCompilable) ast).getHandle(); + return HSTruffleCompilableGen.callIsSameOrSplit(calls, env(), getHandle(), astHandle); } + @TruffleFromLibGraal(GetKnownCallSiteCount) @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); + return HSTruffleCompilableGen.callGetKnownCallSiteCount(calls, env(), getHandle()); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java index ef2fae863c73..b9bc48926451 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java @@ -22,117 +22,107 @@ * 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.TruffleCompilable; import com.oracle.truffle.compiler.TruffleCompilationTask; import com.oracle.truffle.compiler.TruffleSourceLanguagePosition; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; +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.lang.invoke.MethodHandle; +import java.util.LinkedHashMap; import java.util.Map; -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; +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 HSIndirectHandle implements TruffleCompilationTask { +final class HSTruffleCompilationTask extends HSObject implements TruffleCompilationTask { - private static final Handles HANDLES = new Handles(); + private final TruffleFromLibGraalCalls calls; - HSTruffleCompilationTask(Object hsHandle) { - super(hsHandle); + HSTruffleCompilationTask(JNIMethodScope scope, JObject handle, HSTruffleCompilerRuntime runtime) { + super(scope, handle); + this.calls = runtime.calls; } + @TruffleFromLibGraal(IsCancelled) @Override public boolean isCancelled() { - try { - return (boolean) HANDLES.isCancelled.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilationTaskGen.callIsCancelled(calls, env(), getHandle()); } + @TruffleFromLibGraal(IsLastTier) @Override public boolean isLastTier() { - try { - return (boolean) HANDLES.isLastTier.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilationTaskGen.callIsLastTier(calls, env(), getHandle()); } + @TruffleFromLibGraal(HasNextTier) @Override public boolean hasNextTier() { - try { - return (boolean) HANDLES.hasNextTier.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleCompilationTaskGen.callHasNextTier(calls, env(), getHandle()); } + @TruffleFromLibGraal(GetPosition) @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) { + JObject res = HSTruffleCompilationTaskGen.callGetPosition(calls, env(), getHandle(), nodeHandle); + if (res.isNull()) { return null; - } else { - return new HSTruffleSourceLanguagePosition(positionHsHandle); } + return new HSTruffleSourceLanguagePosition(JNIMethodScope.scope(), res, calls); } + @TruffleFromLibGraal(AddTargetToDequeue) @Override public void addTargetToDequeue(TruffleCompilable target) { - try { - HANDLES.addTargetToDequeue.invoke(hsHandle, ((HSTruffleCompilable) target).hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + JObject hsCompilable = ((HSTruffleCompilable) target).getHandle(); + HSTruffleCompilationTaskGen.callAddTargetToDequeue(calls, env(), getHandle(), hsCompilable); } + @TruffleFromLibGraal(SetCallCounts) @Override public void setCallCounts(int total, int inlined) { - try { - HANDLES.setCallCounts.invoke(hsHandle, total, inlined); - } catch (Throwable t) { - throw handleException(t); - } + HSTruffleCompilationTaskGen.callSetCallCounts(calls, env(), getHandle(), total, inlined); } + @TruffleFromLibGraal(AddInlinedTarget) @Override public void addInlinedTarget(TruffleCompilable target) { - try { - HANDLES.addInlinedTarget.invoke(hsHandle, ((HSTruffleCompilable) target).hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + JObject hsCompilable = ((HSTruffleCompilable) target).getHandle(); + HSTruffleCompilationTaskGen.callAddInlinedTarget(calls, env(), getHandle(), hsCompilable); } + @TruffleFromLibGraal(GetDebugProperties) @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); + 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); } - } - - 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); + return result; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java index 8741ddac9cde..97d328f728a8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java @@ -22,84 +22,87 @@ * 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.TruffleCompilable; import com.oracle.truffle.compiler.TruffleCompilationTask; import com.oracle.truffle.compiler.TruffleCompilerListener; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; +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.lang.invoke.MethodHandle; 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.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 HSIndirectHandle implements TruffleCompilerListener { +final class HSTruffleCompilerListener extends HSObject implements TruffleCompilerListener { - private static final Handles HANDLES = new Handles(); + private final TruffleFromLibGraalCalls calls; - HSTruffleCompilerListener(Object hsHandle) { - super(hsHandle); + 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) { - 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); + 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) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - Object hsTask = ((HSTruffleCompilationTask) task).hsHandle; - try { - HANDLES.onTruffleTierFinished.invoke(hsHandle, hsCompilable, hsTask, graph); - } catch (Throwable t) { - throw handleException(t); + 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) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - try { - HANDLES.onGraalTierFinished.invoke(hsHandle, hsCompilable, graph); - } catch (Throwable t) { - throw handleException(t); + 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) { - Object hsCompilable = ((HSTruffleCompilable) compilable).hsHandle; - try { - HANDLES.onFailure.invoke(hsHandle, hsCompilable, reason, bailout, permanentBailout, tier, lazyStackTrace); - } catch (Throwable t) { - throw handleException(t); + 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) { - 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); + 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/libgraal/truffle/HSTruffleCompilerRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java index e645e0fb4cff..23ae63f64c30 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java +++ b/compiler/src/jdk.graal.compiler/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,9 @@ 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.truffle.hotspot.HotSpotTruffleCompilationSupport; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -45,56 +45,66 @@ 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.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(); +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; - - 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); + final TruffleFromLibGraalCalls calls; + + 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 +118,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 +172,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 +183,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 +219,31 @@ 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); - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java index 0895789ec68c..0b27e25e35e7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java @@ -22,106 +22,86 @@ * 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.TruffleSourceLanguagePosition; -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id; +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.lang.invoke.MethodHandle; import java.net.URI; -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; +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 HSIndirectHandle implements TruffleSourceLanguagePosition { +final class HSTruffleSourceLanguagePosition extends HSObject implements TruffleSourceLanguagePosition { - private static final Handles HANDLES = new Handles(); + private final TruffleFromLibGraalCalls calls; - HSTruffleSourceLanguagePosition(Object hsHandle) { - super(hsHandle); + HSTruffleSourceLanguagePosition(JNIMethodScope scope, JObject handle, TruffleFromLibGraalCalls calls) { + super(scope, handle); + this.calls = calls; } + @TruffleFromLibGraal(GetDescription) @Override public String getDescription() { - try { - return (String) HANDLES.getDescription.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetDescription(calls, env, getHandle())); } + @TruffleFromLibGraal(GetOffsetEnd) @Override public int getOffsetEnd() { - try { - return (int) HANDLES.getOffsetEnd.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleSourceLanguagePositionGen.callGetOffsetEnd(calls, JNIMethodScope.env(), getHandle()); } + @TruffleFromLibGraal(GetOffsetStart) @Override public int getOffsetStart() { - try { - return (int) HANDLES.getOffsetStart.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleSourceLanguagePositionGen.callGetOffsetStart(calls, JNIMethodScope.env(), getHandle()); } + @TruffleFromLibGraal(GetLineNumber) @Override public int getLineNumber() { - try { - return (int) HANDLES.getLineNumber.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleSourceLanguagePositionGen.callGetLineNumber(calls, JNIMethodScope.env(), getHandle()); } + @TruffleFromLibGraal(GetURI) @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); + 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() { - try { - return (String) HANDLES.getLanguage.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetLanguage(calls, env, getHandle())); } + @TruffleFromLibGraal(GetNodeId) @Override public int getNodeId() { - try { - return (int) HANDLES.getNodeId.invoke(hsHandle); - } catch (Throwable t) { - throw handleException(t); - } + return HSTruffleSourceLanguagePositionGen.callGetNodeId(calls, JNIMethodScope.env(), getHandle()); } + @TruffleFromLibGraal(GetNodeClassName) @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); + JNIEnv env = JNIMethodScope.env(); + return JNIUtil.createString(env, HSTruffleSourceLanguagePositionGen.callGetNodeClassName(calls, env, getHandle())); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java index 3619c9c32819..4f0d03adee62 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java +++ b/compiler/src/jdk.graal.compiler/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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java index 9e9819d0beb0..f3dcccabf4f1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java +++ b/compiler/src/jdk.graal.compiler/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/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java new file mode 100644 index 000000000000..0d46c8da0c48 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java @@ -0,0 +1,541 @@ +/* + * 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.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 jdk.graal.nativeimage.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); + 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") + @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) { + CompilationResultInfo compilationResultInfo = LibGraalObjectHandles.resolve(handle, CompilationResultInfo.class); + return compilationResultInfo.getCompilationId(); + } + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(env, t); + return -1; + } + } + + @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/libgraal/truffle/LibGraalTruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java index 3ac8c3faa522..1adaebafda5a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java +++ b/compiler/src/jdk.graal.compiler/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/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java index be7781e34e08..2ca597746e75 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java @@ -22,14 +22,19 @@ * 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 +52,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,35 +64,40 @@ 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)); - this.previousRuntime = environment = new LibGraalTruffleHostEnvironment(runtime, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getMetaAccess()); - return environment; - } + 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; } private static HSTruffleCompilerRuntime hsRuntime(TruffleHostEnvironment environment) { 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/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java new file mode 100644 index 000000000000..85612be8a82d --- /dev/null +++ b/compiler/src/jdk.graal.compiler/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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java index 644cee8f9809..f32440524246 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java +++ b/compiler/src/jdk.graal.compiler/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/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java index 8f7c013202fc..4009f66f5972 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java @@ -22,17 +22,19 @@ * 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.hotspot.libgraal.TruffleFromLibGraal.Id; +import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; 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 org.graalvm.jniutils.JNI.JClass; +import org.graalvm.jniutils.JNI.JNIEnv; +import org.graalvm.jniutils.JNI.JavaVM; +import org.graalvm.jniutils.JNIUtil; -import java.lang.invoke.MethodHandle; - -import static jdk.graal.compiler.hotspot.libgraal.truffle.BuildTime.getHostMethodHandleOrFail; +import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnIsolateShutdown; @ServiceProvider(JVMCIServiceLocator.class) public class TruffleLibGraalShutdownHook extends JVMCIServiceLocator { @@ -48,30 +50,29 @@ protected S getProvider(Class service) { return null; } - static void registerShutdownHook() { - registeredHook = new ShutdownHook(); + static void registerShutdownHook(JNIEnv env, JClass runtimeClass) { + JavaVM vm = JNIUtil.GetJavaVM(env); + ShutdownHook hook = registeredHook; + assert hook == null || hook.javaVm.isNull() || hook.javaVm.equal(vm); + registeredHook = new ShutdownHook(vm, new TruffleFromLibGraalCalls(env, runtimeClass)); } static class ShutdownHook implements HotSpotVMEventListener { - private static final Handles HANDLES = new Handles(); + private final JavaVM javaVm; + private final TruffleFromLibGraalCalls calls; - ShutdownHook() { + ShutdownHook(JavaVM javaVm, TruffleFromLibGraalCalls calls) { + this.javaVm = javaVm; + this.calls = calls; } @Override + @TruffleFromLibGraal(OnIsolateShutdown) public void notifyShutdown() { - try { - HANDLES.onIsolateShutdown.invoke(IsolateUtil.getIsolateID()); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable t) { - throw new RuntimeException(t); - } + JNIEnv env = JNIUtil.GetEnv(javaVm); + assert env.isNonNull(); + TruffleLibGraalShutdownHookGen.callOnIsolateShutdown(calls, env, IsolateUtil.getIsolateID()); } } - - private static final class Handles { - final MethodHandle onIsolateShutdown = getHostMethodHandleOrFail(Id.OnIsolateShutdown); - } } 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..c2e15a554168 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 @@ -35,6 +35,7 @@ import jdk.graal.compiler.debug.TimerKey; import jdk.graal.compiler.lir.gen.LIRGenerationResult; import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.nativeimage.LibGraalRuntime; import jdk.vm.ci.code.TargetDescription; public class LIRPhaseSuite extends LIRPhase implements PhasePlan> { @@ -105,10 +106,15 @@ 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(); + if (GraalServices.isInLibgraal()) { + // 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())) { + LibGraalRuntime.notifyLowMemoryPoint(false); + LibGraalRuntime.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..d8016300ffb2 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 @@ -86,6 +93,7 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re return false; } + ResolvedJavaMethod thisExecuteMethod = getExecuteMethod(b); if (inImageBuildtimeCode()) { // Calls to the @Fold method from the generated fold plugin shouldn't be folded. This is // detected by comparing the class names of the current plugin and the method being @@ -98,7 +106,6 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re } } - ResolvedJavaMethod thisExecuteMethod = getExecuteMethod(b); if (b.getMethod().equals(thisExecuteMethod)) { return true; } 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..3640ddf592b4 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 @@ -39,11 +39,11 @@ import java.util.function.Function; import java.util.regex.Pattern; +import jdk.graal.nativeimage.LibGraalLoader; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; - -import jdk.graal.compiler.debug.GraalError; +import org.graalvm.nativeimage.ImageInfo; /** * This class contains methods for parsing Graal options and matching them against a set of @@ -56,8 +56,8 @@ public class OptionsParser { * * @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. + * field is only non-null when {@link OptionsParser} is loaded by a + * {@link jdk.graal.nativeimage.LibGraalLoader}. * @param enterpriseOptions {@linkplain OptionKey#getName() names} of enterprise options */ public record LibGraalOptionsInfo(EconomicMap descriptors, Set enterpriseOptions) { @@ -68,9 +68,11 @@ public static LibGraalOptionsInfo create() { /** * Compiler options info available in libgraal. This field is only non-null when - * {@link OptionsParser} is loaded by the LibGraalClassLoader. + * {@link OptionsParser} is loaded by a {@link jdk.graal.nativeimage.LibGraalLoader} and + * {@linkplain ImageInfo#inImageBuildtimeCode libgraal is being built}. */ - private static LibGraalOptionsInfo libgraalOptions; + public static final LibGraalOptionsInfo libgraalOptions = inImageBuildtimeCode() && + OptionsParser.class.getClassLoader() instanceof LibGraalLoader ? LibGraalOptionsInfo.create() : null; /** * Gets an iterable of available {@link OptionDescriptors}. @@ -81,10 +83,10 @@ public static Iterable getOptionsLoader() { return List.of(new OptionDescriptorsMap(Objects.requireNonNull(libgraalOptions.descriptors, "missing options"))); } boolean inLibGraal = libgraalOptions != null; - if (inLibGraal && inImageBuildtimeCode()) { + if (inLibGraal) { /* - * Graal code is being run in the context of the LibGraalClassLoader while building - * libgraal so use the LibGraalClassLoader to load the OptionDescriptors. + * Graal code being run is loaded by a LibGraalLoader while building libgraal so use the + * loader to load the OptionDescriptors. */ ClassLoader myCL = OptionsParser.class.getClassLoader(); return ServiceLoader.load(OptionDescriptors.class, myCL); @@ -99,14 +101,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 +367,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..089c0807c6a7 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,15 @@ import java.lang.ref.Cleaner; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.nativeimage.LibGraalLoader; +import jdk.graal.nativeimage.hosted.GlobalData; 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 @@ -44,13 +51,26 @@ public class GlobalAtomicLong { /** * Cleaner for freeing {@link #address}. */ + @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. This field is transformed + * during native image building into a supplier backed by {@link GlobalData} + */ + private final Supplier addressSupplier; + /** * Value to which the value will be initialized. */ @@ -61,8 +81,31 @@ 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 { + if (ImageInfo.inImageBuildtimeCode() && GlobalAtomicLong.class.getClassLoader() instanceof LibGraalLoader) { + addressSupplier = GlobalData.createGlobal(initialValue); + } else { + addressSupplier = () -> { + if (ImageInfo.inImageRuntimeCode()) { + throw GraalError.shouldNotReachHere("The addressSupplier field value should have been replaced at image build time"); + } + 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..f30eca33ff76 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,38 +30,35 @@ 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 java.util.Set; +import jdk.graal.compiler.core.ArchitectureSpecific; +import jdk.graal.nativeimage.LibGraalLoader; +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. */ 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. - */ - public static boolean isBuildingLibgraal() { - return Services.IS_BUILDING_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 @@ -73,15 +70,64 @@ public static boolean isInLibgraal() { /** * The set of services available in libgraal. This field is only non-null when - * {@link GraalServices} is loaded by the LibGraalClassLoader. + * {@link GraalServices} is loaded by a {@link LibGraalLoader}. + */ + 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; + } + } + + /** + * 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 { + ClassLoader cl = GraalServices.class.getClassLoader(); + if (inImageBuildtimeCode() && cl instanceof LibGraalLoader libgraalLoader) { + libgraalServices = new HashMap<>(); + Set libgraalServicesModules = libgraalLoader.getServicesModules(); + Map modules = libgraalLoader.getModuleMap(); + String arch = getJVMCIArch(); + modules.entrySet().stream()// + .filter(e -> libgraalServicesModules.contains(e.getValue()))// + .map(Map.Entry::getKey)// + .map(GraalServices::loadClassOrNull)// + .filter(c -> c != null && c.getAnnotation(LibGraalService.class) != null)// + .forEach(service -> addProviders(arch, service)); + } else { + libgraalServices = null; + } } private GraalServices() { @@ -104,6 +150,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 +173,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 +343,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 +517,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..854b40dec5c7 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,10 @@ */ package jdk.graal.compiler.serviceprovider; +import jdk.graal.nativeimage.LibGraalRuntime; +import org.graalvm.nativeimage.CurrentIsolate; +import org.graalvm.nativeimage.ImageInfo; + /** * Utility methods that provide access to isolate details. */ @@ -33,7 +37,10 @@ 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(); + if (ImageInfo.inImageRuntimeCode()) { + return CurrentIsolate.getIsolate().rawValue(); + } + return 0L; } /** @@ -42,7 +49,10 @@ public static long getIsolateAddress() { * process. */ public static long getIsolateID() { - return VMSupport.getIsolateID(); + if (ImageInfo.inImageRuntimeCode()) { + return LibGraalRuntime.getIsolateID(); + } + return 0L; } /** 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/compiler/src/jdk.graal.nativeimage/snapshot.sigtest b/compiler/src/jdk.graal.nativeimage/snapshot.sigtest new file mode 100644 index 000000000000..1456a58e38cc --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/snapshot.sigtest @@ -0,0 +1,34 @@ +#Signature file v4.1 +#Version + +CLSS public abstract interface jdk.graal.nativeimage.LibGraalLoader +meth public abstract java.nio.file.Path getJavaHome() +meth public abstract java.util.Set getServicesModules() +meth public abstract java.lang.ClassLoader getRuntimeClassLoader() +meth public abstract java.util.Map getModuleMap() + +CLSS public final jdk.graal.nativeimage.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 jdk.graal.nativeimage.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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java new file mode 100644 index 000000000000..a75d5753ce43 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java @@ -0,0 +1,65 @@ +/* + * 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.nativeimage; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; + +/** + * 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 the {@code java.home} of the JDK whose runtime image contains the Graal and JVMCI + * classes from which libgraal will be built. + */ + Path getJavaHome(); + + /** + * Gets the ClassLoader that should be seen at image runtime if a class was loaded at image + * build-time by this loader. + */ + ClassLoader getRuntimeClassLoader(); + + /** + * 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 getModuleMap(); + + /** + * Gets the names of the modules containing classes that can be annotated by + * {@code LibGraalService}. + */ + Set getServicesModules(); +} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java new file mode 100644 index 000000000000..435a53be6018 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java @@ -0,0 +1,87 @@ +/* + * 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.nativeimage; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; + +import org.graalvm.nativeimage.ImageSingletons; + +import jdk.graal.nativeimage.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. + * + * @return a non-zero value + */ + 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. A typical implementation will delegate to an OS function that kills the process. + * In the context of libgraal, it will call 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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java new file mode 100644 index 000000000000..3f87d8dd9338 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java @@ -0,0 +1,54 @@ +/* + * 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.nativeimage.hosted; + +import jdk.graal.nativeimage.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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java new file mode 100644 index 000000000000..c7f9506b3e17 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java @@ -0,0 +1,35 @@ +/* + * 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. + */ +/* + @ApiInfo( + group="Native Image LibGraal extensions" + ) + */ +/** + * Extensions to the GraalVM SDK Native Image API to customize building libgraal. + * + * @since 25 + */ +package jdk.graal.nativeimage.hosted; diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java new file mode 100644 index 000000000000..1e1308db26d3 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java @@ -0,0 +1,32 @@ +/* + * 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.nativeimage.impl; + +import java.util.function.Supplier; + +public interface GlobalDataSupport { + + Supplier createGlobal(long initialValue); +} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java new file mode 100644 index 000000000000..d8572ce02120 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java @@ -0,0 +1,36 @@ +/* + * 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.nativeimage.impl; + +public interface LibGraalRuntimeSupport { + + void processReferences(); + + void notifyLowMemoryPoint(boolean suggestFullGC); + + long getIsolateID(); + + void fatalError(String message); +} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java new file mode 100644 index 000000000000..c0f173932130 --- /dev/null +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java @@ -0,0 +1,35 @@ +/* + * 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. + */ +/* + @ApiInfo( + group="Native Image LibGraal extensions" + ) + */ +/** + * Extensions to the GraalVM SDK Native Image API to customize building libgraal. + * + * @since 25 + */ +package jdk.graal.nativeimage; diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 68982d10b4bc..7bb74bd70391 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', @@ -143,7 +143,13 @@ def upx(args): third_party_license_files=[], dependencies=[], jar_distributions=[], - boot_jars=['sdk:WORD', 'sdk:COLLECTIONS', 'sdk:NATIVEIMAGE'], + boot_jars=[ + 'sdk:WORD', + 'sdk:COLLECTIONS', + 'sdk:NATIVEIMAGE', + 'sdk:NATIVEBRIDGE', + 'sdk:JNIUTILS' + ], stability="supported", ) mx_sdk_vm.register_graalvm_component(graal_sdk_compiler_component) @@ -158,7 +164,7 @@ def upx(args): third_party_license_files=[], dependencies=['sdkc'], jar_distributions=[], - boot_jars=['sdk:NATIVEIMAGE'], + boot_jars=['sdk:NATIVEIMAGE', 'compiler:GRAAL_NATIVEIMAGE'], stability="supported", ) mx_sdk_vm.register_graalvm_component(graalvm_sdk_native_image_component) 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/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 65d06bad20db..f655740cc70b 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -1474,8 +1474,7 @@ def _native_image_launcher_extra_jvm_args(): libgraal_jar_distributions = [ 'sdk:NATIVEBRIDGE', 'sdk:JNIUTILS', - 'compiler:LIBGRAAL_LOADER', - 'substratevm:LIBGRAAL_LIBRARY'] + 'compiler:LIBGRAAL_LOADER'] def allow_build_path_in_libgraal(): """ @@ -1505,33 +1504,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 +1522,7 @@ 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", '-H:-UseServiceLoaderFeature', '-H:+AllowFoldMethods', '-Dtruffle.TruffleRuntime=', @@ -1548,6 +1530,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..a246a875b0b9 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1386,70 +1386,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 +1713,7 @@ "transitive org.graalvm.nativeimage.pointsto", "org.graalvm.collections", "org.graalvm.truffle.compiler", + "jdk.graal.nativeimage" ], "uses" : [ "org.graalvm.nativeimage.Platform", @@ -2036,21 +1973,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 # 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..5a9019b31503 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 jdk.graal.compiler.libgraal.LibGraalFeature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -68,6 +69,7 @@ import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.util.Providers; +import org.graalvm.nativeimage.hosted.RuntimeSystemProperties; @AutomaticallyRegisteredFeature class GenScavengeGCFeature implements InternalFeature { @@ -129,6 +131,9 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { ImageSingletons.add(CommittedMemoryProvider.class, createCommittedMemoryProvider()); } + String gcName = Heap.getHeap().getGC().getName(); + RuntimeSystemProperties.register(LibGraalFeature.NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", gcName); + // Needed for the barrier set. access.registerAsUsed(Object[].class); } 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..9bd5c8922e8e --- /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 jdk.graal.nativeimage.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/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/libgraal/LibGraalRuntimeSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java new file mode 100644 index 000000000000..be2c1dc81a26 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/libgraal/LibGraalRuntimeSupportImpl.java @@ -0,0 +1,58 @@ +/* + * 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 org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.impl.IsolateSupport; + +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.util.VMError; + +import jdk.graal.nativeimage.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 ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); + } + + @Override + public void fatalError(String message) { + throw VMError.shouldNotReachHere(message); + } +} 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..bb2e20200d05 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); + 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..fe1f21163b99 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 jdk.graal.nativeimage.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..16a1af639e9c 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,13 +28,12 @@ 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 jdk.graal.compiler.graph.Edges; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; @@ -42,20 +41,15 @@ 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; @@ -230,42 +222,6 @@ public static long 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(); - } -} - /* * The following substitutions replace methods where reflection is used in the Graal code. */ @@ -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..36202851abff 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 jdk.graal.nativeimage.LibGraalLoader; import jdk.internal.loader.ClassLoaders; import jdk.vm.ci.meta.JavaConstant; @@ -121,9 +121,9 @@ 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(); 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..51659fa7b383 --- /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 jdk.graal.nativeimage.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..c47649e215f5 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 jdk.graal.nativeimage.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.getModuleMap().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/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 3f775ec9680a..0e9d89b72406 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -239,6 +239,7 @@ private static void transitiveRequires(boolean verbose, Module requiringModule, /* graal */ potentialNeedModule.getName().startsWith("org.graalvm.") || potentialNeedModule.getName().startsWith("jdk.graal.compiler") || + potentialNeedModule.getName().startsWith("jdk.graal.nativeimage") || /* enterprise graal */ potentialNeedModule.getName().startsWith("com.oracle.graal.") || /* exclude all truffle modules */ 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..e418fce47499 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("jdk.graal.nativeimage", 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..f6991a0e8ff5 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,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import jdk.graal.nativeimage.LibGraalLoader; import org.graalvm.collections.EconomicSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; @@ -189,6 +190,16 @@ public boolean maybeInitializeAtBuildTime(Class clazz) { * class initialization fails. */ InitKind ensureClassInitialized(Class clazz, boolean allowErrors) { + LibGraalLoader libGraalLoader = loader.classLoaderSupport.getLibGraalLoader(); + Thread thread = Thread.currentThread(); + ClassLoader restoreCCL = null; + ClassLoader clazzLoader = clazz.getClassLoader(); + if (libGraalLoader != null && (ClassLoader) libGraalLoader == clazzLoader) { + // Graal and JVMCI make use of ServiceLoader which uses the + // context class loader so it needs to be the libgraal loader. + restoreCCL = thread.getContextClassLoader(); + thread.setContextClassLoader(clazz.getClassLoader()); + } try { loader.watchdog.recordActivity(); /* @@ -234,6 +245,10 @@ InitKind ensureClassInitialized(Class clazz, boolean allowErrors) { throw UserError.abort(t, "%s", msg); } + } finally { + if (restoreCCL != null) { + thread.setContextClassLoader(restoreCCL); + } } } 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 index d843a040f927..040c6fbfa7c5 100644 --- 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 @@ -1,12 +1,10 @@ -Specify the fully qualified class name of the LibGraalClassLoader implementation that gets used for building libgraal. +Specify the fully qualified name of a class that implements jdk.graal.nativeimage.LibGraalLoader. 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: +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 from classes managed by the custom loader are processed. - 3. All @TargetClass substitutions in classes managed by the custom loader are processed. + 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.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..6866faf10671 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() { @@ -1052,11 +1046,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..d9c3694b9328 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", + "jdk.graal.nativeimage", + "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" : { From acefdc1ee6fee40b4f77beb8ad14586886deeae2 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 5 Feb 2025 16:38:08 +0100 Subject: [PATCH 3/9] added LibGraalSupport SPI --- compiler/CHANGELOG.md | 3 +- compiler/mx.compiler/mx_compiler.py | 9 +- compiler/mx.compiler/suite.py | 175 ++++++---- .../loader/HostedLibGraalClassLoader.java | 175 ++++++++-- ...graal.compiler.core.common.LibGraalSupport | 1 + .../compiler/libgraal/BeforeJDK8346781.java | 0 .../compiler/libgraal/GetCompilerConfig.java | 1 + .../graal/compiler/libgraal/GetJNIConfig.java | 0 .../graal/compiler/libgraal/JDKLatest.java | 0 .../libgraal/LibGraalEntryPoints.java | 4 +- .../compiler/libgraal/LibGraalFeature.java | 97 ++---- .../libgraal/LibGraalJNIMethodScope.java | 0 .../libgraal/LibGraalNativeBridgeSupport.java | 0 .../libgraal/LibGraalSubstitutions.java | 11 + .../libgraal/LibGraalSupportImpl.java | 319 ++++++++++++++++++ .../libgraal/truffle/FromLibGraalCalls.java | 0 .../compiler/libgraal/truffle/HSConsumer.java | 0 .../libgraal/truffle/HSTruffleCompilable.java | 0 .../truffle/HSTruffleCompilationTask.java | 0 .../truffle/HSTruffleCompilerListener.java | 0 .../truffle/HSTruffleCompilerRuntime.java | 9 +- .../HSTruffleSourceLanguagePosition.java | 0 .../truffle/LibGraalObjectHandleScope.java | 0 .../truffle/LibGraalObjectHandles.java | 0 .../truffle/LibGraalTruffleEntryPoints.java | 17 +- .../LibGraalTruffleHostEnvironment.java | 0 .../LibGraalTruffleHostEnvironmentLookup.java | 11 +- .../LibGraalTruffleScopeEntryPoints.java | 0 .../truffle/TruffleFromLibGraalCalls.java | 0 .../test/HotSpotGraalOptionValuesTest.java | 22 -- ...nent.java => ContextClassLoaderScope.java} | 38 ++- .../graal/compiler/core/common/Fields.java | 32 +- .../compiler/core/common/LibGraalSupport.java | 187 ++++++++++ .../graal/compiler/core/phases/BaseTier.java | 16 +- .../graal/compiler/debug/IgvDumpChannel.java | 3 +- .../src/jdk/graal/compiler/graph/Edges.java | 10 +- .../jdk/graal/compiler/graph/NodeClass.java | 24 +- .../compiler/hotspot/CompilationTask.java | 19 +- .../{libgraal => hotspot}/CompilerConfig.java | 8 +- .../hotspot/CompilerConfigurationFactory.java | 2 +- .../hotspot/HotSpotGraalCompiler.java | 60 +--- .../hotspot/HotSpotGraalOptionValues.java | 75 +--- .../compiler/hotspot/HotSpotGraalRuntime.java | 84 +---- .../truffle/TruffleLibGraalShutdownHook.java | 78 ----- .../compiler/lir/phases/LIRPhaseSuite.java | 19 +- .../GeneratedInvocationPlugin.java | 2 +- .../graal/compiler/options/OptionsParser.java | 22 +- .../serviceprovider/GlobalAtomicLong.java | 20 +- .../serviceprovider/GraalServices.java | 19 +- .../compiler/serviceprovider/IsolateUtil.java | 14 +- .../jdk/graal/nativeimage/LibGraalLoader.java | 2 +- .../graal/nativeimage/LibGraalRuntime.java | 6 +- .../nativeimage/hosted/package-info.java | 2 +- .../nativeimage/impl/GlobalDataSupport.java | 8 + .../impl/LibGraalRuntimeSupport.java | 19 +- .../jdk/graal/nativeimage/package-info.java | 2 +- sdk/mx.sdk/mx_sdk.py | 8 +- substratevm/mx.substratevm/mx_substratevm.py | 5 + substratevm/mx.substratevm/suite.py | 2 + .../graal/GenScavengeGCFeature.java | 4 +- .../graal/hosted/FieldsOffsetsFeature.java | 2 +- .../ClassInitializationSupport.java | 21 +- .../AnnotationSubstitutionProcessor.java | 1 - 63 files changed, 1018 insertions(+), 650 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler.libgraal/src/META-INF/services/jdk.graal.compiler.core.common.LibGraalSupport rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java (99%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/GetJNIConfig.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/JDKLatest.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java (99%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/LibGraalFeature.java (84%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java (86%) create mode 100644 compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSupportImpl.java rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java (96%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/HSTruffleSourceLanguagePosition.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandles.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java (98%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java (88%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java (100%) rename compiler/src/{jdk.graal.compiler => jdk.graal.compiler.libgraal}/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java (100%) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/{FeatureComponent.java => ContextClassLoaderScope.java} (50%) create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/{libgraal => hotspot}/CompilerConfig.java (94%) delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index 3fbd1502e1c0..fd6f78b4a83e 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -4,7 +4,8 @@ This changelog summarizes newly introduced optimizations and other compiler rela ## GraalVM for JDK 25 (Internal Version 25.0.0) * (GR-60088): This PR adds the `jdk.graal.nativeimage` SDK module. With this module, all logic for building - libgraal has been moved into the core compiler. There is no dependency on Native Image internals. This + 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. diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 31fcc2c01ab5..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 @@ -506,12 +506,7 @@ def _check_forbidden_imports(projects, package_substrings, exceptions=None): def compiler_gate_runner(suites, unit_test_runs, bootstrap_tests, tasks, extraVMarguments=None, extraUnitTestArguments=None): with Task('CheckForbiddenImports:Compiler', tasks, tags=['style']) as t: # Ensure HotSpot-independent compiler classes do not import HotSpot-specific classes - if t: - exceptions = { - 'Fields.java': 'need to register libgraal feature components', - 'NodeClass.java': 'need to register libgraal feature components' - } - _check_forbidden_imports([mx.project('jdk.graal.compiler')], ('hotspot', 'libgraal'), exceptions) + if t: _check_forbidden_imports([mx.project('jdk.graal.compiler')], ('hotspot', 'libgraal')) with Task('JDK_java_base_test', tasks, tags=['javabasetest'], report=True) as t: if t: java_base_unittest(_remove_empty_entries(extraVMarguments) + []) diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 2a18088793cf..5e1cbda6ffd9 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -164,27 +164,13 @@ # ------------- Graal ------------- - # Native Image API extensions for libgraal. - "jdk.graal.nativeimage" : { - "subDir" : "src", - "sourceDirs" : ["src"], - "dependencies" : [ - "sdk:NATIVEIMAGE" - ], - "checkstyle" : "jdk.graal.compiler", - "javaCompliance" : "21+" - }, - "jdk.graal.compiler" : { "subDir" : "src", "sourceDirs" : ["src"], "dependencies" : [ - "GRAAL_NATIVEIMAGE", - "sdk:JNIUTILS", "sdk:WORD", "sdk:COLLECTIONS", "sdk:NATIVEIMAGE", - "sdk:NATIVEBRIDGE", "truffle:TRUFFLE_COMPILER", ], "requires" : [ @@ -193,7 +179,6 @@ ], "requiresConcealed" : { "java.base" : [ - "jdk.internal.module", "jdk.internal.misc" ], "jdk.internal.vm.ci" : [ @@ -224,8 +209,7 @@ "jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider" ], "annotationProcessors" : [ - "GRAAL_PROCESSOR", - "truffle:TRUFFLE_LIBGRAAL_PROCESSOR", + "GRAAL_PROCESSOR" ], "checkPackagePrefix": "false", "checkstyleVersion" : "10.21.0", @@ -487,13 +471,59 @@ "graalCompilerSourceEdition": "ignore", }, + # ------------- libgraal ------------- + + # Native Image API extensions for libgraal. + "jdk.graal.nativeimage" : { + "subDir" : "src", + "sourceDirs" : ["src"], + "dependencies" : [ + "sdk:NATIVEIMAGE" + ], + "checkstyle" : "jdk.graal.compiler", + "javaCompliance" : "21+" + }, + + # 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", + "GRAAL_NATIVEIMAGE", + "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.nativeimage", + "GRAAL_NATIVEIMAGE", ], "requiresConcealed" : { "java.base" : [ @@ -567,45 +597,13 @@ "maven": False, }, - "GRAAL_NATIVEIMAGE" : { - "subDir" : "src", - "dependencies" : [ - "jdk.graal.nativeimage", - ], - "distDependencies" : ["sdk:NATIVEIMAGE"], - "javadocType": "api", - "moduleInfo" : { - "name" : "jdk.graal.nativeimage", - "requires" : [ - "transitive org.graalvm.nativeimage", - ], - "exports" : [ - "jdk.graal.nativeimage", - "jdk.graal.nativeimage.hosted", - "jdk.graal.nativeimage.impl to org.graalvm.nativeimage.builder", - ], - "uses" : [], - "opens" : [], - }, - "description" : "Native Image API extensions for libgraal.", - "maven": { - "tag": ["default", "public"], - }, - }, - "GRAAL" : { # This distribution defines a module. "moduleInfo" : { "name" : "jdk.graal.compiler", - "requires" : [ - # These dependencies are only required when building libgraal. - # Running jargraal works without them so make them optional - # (i.e., "static") dependencies. - "static jdk.graal.nativeimage", - "static org.graalvm.nativebridge" - ], "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, @@ -631,6 +629,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", @@ -649,12 +648,9 @@ "GRAAL_VERSION", ], "distDependencies" : [ - "GRAAL_NATIVEIMAGE", "sdk:COLLECTIONS", "sdk:WORD", "sdk:NATIVEIMAGE", - "sdk:NATIVEBRIDGE", - "sdk:JNIUTILS", "truffle:TRUFFLE_COMPILER", ], "allowsJavadocWarnings": True, @@ -685,6 +681,64 @@ }, }, + "GRAAL_NATIVEIMAGE" : { + "subDir" : "src", + "dependencies" : [ + "jdk.graal.nativeimage", + ], + "distDependencies" : ["sdk:NATIVEIMAGE"], + "javadocType": "api", + "moduleInfo" : { + "name" : "jdk.graal.nativeimage", + "requires" : [ + "transitive org.graalvm.nativeimage", + ], + "exports" : [ + "jdk.graal.nativeimage", + "jdk.graal.nativeimage.hosted", + "jdk.graal.nativeimage.impl to org.graalvm.nativeimage.builder", + ], + "uses" : [], + "opens" : [], + }, + "description" : "Native Image API extensions for libgraal.", + "maven": { + "tag": ["default", "public"], + }, + }, + + "LIBGRAAL_LOADER" : { + "subDir": "src", + "dependencies" : [ + "jdk.graal.compiler.libgraal.loader" + ], + "distDependencies" : [ + "GRAAL_NATIVEIMAGE", + "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", + "GRAAL_NATIVEIMAGE", + "sdk:JNIUTILS", + "sdk:NATIVEIMAGE", + "sdk:NATIVEBRIDGE" + ], + "maven": False, + }, + "GRAAL_COMPILER_WHITEBOX_MICRO_BENCHMARKS" : { "subDir" : "src", "dependencies" : [ @@ -762,17 +816,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/libgraal/loader/HostedLibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java index 479b0bd64569..87d1828f03d3 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java +++ b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java @@ -26,16 +26,19 @@ import jdk.graal.nativeimage.LibGraalLoader; import jdk.internal.jimage.BasicImageReader; -import jdk.internal.jimage.ImageLocation; +import jdk.internal.module.ModulePath; import jdk.internal.module.Modules; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; 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; @@ -43,6 +46,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; @@ -51,11 +55,14 @@ 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.Collectors; +import java.util.stream.Stream; /** - * 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. */ @Platforms(Platform.HOSTED_ONLY.class) public final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalLoader { @@ -66,15 +73,85 @@ public final class HostedLibGraalClassLoader extends ClassLoader implements LibG */ private static final String LIBGRAAL_JAVA_HOME_PROPERTY_NAME = "libgraal.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. */ private final BasicImageReader imageReader; + /** + * A resource located in the jimage file or on the module path. + */ + 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; + } + + /** + * 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 resources = new HashMap<>(); + private final Map resources = new HashMap<>(); /** * Map from a service name to a list of providers. @@ -88,21 +165,20 @@ public final class HostedLibGraalClassLoader extends ClassLoader implements LibG private final Map modules; /** - * Modules in which Graal and JVMCI classes are defined. + * Modules containing classes that can be annotated by {@code LibGraalService}. */ - private static final Set LIBGRAAL_MODULES = Set.of( - "jdk.internal.vm.ci", + private static final Set LIBGRAAL_SERVICES_MODULES = Set.of( "jdk.graal.compiler", + "jdk.graal.compiler.libgraal", "org.graalvm.truffle.compiler", "com.oracle.graal.graal_enterprise"); /** - * Modules containing classes that can be annotated by {@code LibGraalService}. + * Modules in which Graal and JVMCI classes are defined that this loader will load. */ - private static final Set LIBGRAAL_SERVICES_MODULES = Set.of( - "jdk.graal.compiler", - "org.graalvm.truffle.compiler", - "com.oracle.graal.graal_enterprise"); + private static final Set LIBGRAAL_MODULES = Stream.concat( + LIBGRAAL_SERVICES_MODULES.stream(), Stream.of("jdk.internal.vm.ci")) // + .collect(Collectors.toUnmodifiableSet()); static { ClassLoader.registerAsParallelCapable(); @@ -115,9 +191,23 @@ public Path getJavaHome() { return 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()); + // This loader delegates to the class loader that loaded its own class. + super(LibGraalClassLoader.LOADER_NAME, HostedLibGraalClassLoader.class.getClassLoader()); try { /* @@ -144,7 +234,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")) { @@ -160,6 +250,30 @@ 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); } catch (IOException e) { @@ -196,18 +310,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); } @@ -242,8 +352,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); @@ -278,10 +388,13 @@ public URLConnection openConnection(URL u) { 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()); 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/libgraal/BeforeJDK8346781.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/BeforeJDK8346781.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java similarity index 99% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java index ede2b814f431..a50337117424 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetCompilerConfig.java @@ -36,6 +36,7 @@ import java.util.stream.Collectors; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.CompilerConfig; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.util.ObjectCopier; import org.graalvm.nativeimage.ImageInfo; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/GetJNIConfig.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/JDKLatest.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/JDKLatest.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/JDKLatest.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/JDKLatest.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java similarity index 99% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java index 024734a69312..2636fed1451f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java @@ -215,7 +215,7 @@ private static long compileMethod(JNIEnv jniEnv, * libgraal doesn't use a dedicated reference handler thread, so we trigger the * reference handling manually when a compilation finishes. */ - HotSpotGraalRuntime.doReferenceHandling(); + LibGraalSupportImpl.doReferenceHandling(); } } @@ -265,7 +265,7 @@ private static long hashConstantOopFields(JNIEnv jniEnv, if (verbose) { System.out.println("calling reference handling"); } - HotSpotGraalRuntime.doReferenceHandling(); + LibGraalSupportImpl.doReferenceHandling(); if (verbose) { System.out.println("called reference handling"); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java similarity index 84% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java index 0e95d5baa57a..74b2d60dd618 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalFeature.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java @@ -26,6 +26,7 @@ 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; @@ -67,10 +68,8 @@ import jdk.graal.compiler.graph.Edges; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.core.common.FeatureComponent; import jdk.graal.nativeimage.LibGraalLoader; import jdk.vm.ci.hotspot.HotSpotModifiers; -import org.graalvm.nativeimage.hosted.RuntimeSystemProperties; /** * This feature builds the libgraal shared library (e.g., libjvmcicompiler.so on linux). @@ -78,38 +77,6 @@ @Platforms(Platform.HOSTED_ONLY.class) public final class LibGraalFeature implements Feature { - /** - * Prefix to be used when {@linkplain RuntimeSystemProperties#register registering} properties - * describing the image configuration for libgraal. This is analogous to the configuration info - * displayed by {@code -XshowSettings}. - * - * For example: - * - *
-     * RuntimeSystemProperties.register(NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", "serial");
-     * 
- */ - public static final String NATIVE_IMAGE_SETTING_KEY_PREFIX = "org.graalvm.nativeimage.setting."; - - private static LibGraalFeature singleton; - - public LibGraalFeature() { - synchronized (LibGraalFeature.class) { - GraalError.guarantee(singleton == null, "only a single %s instance should be created", LibGraalFeature.class.getName()); - singleton = this; - } - } - - /** - * @return the singleton {@link LibGraalFeature} instance if called within the context of the - * class loader used to load the code being compiled into the libgraal image, otherwise - * null - */ - public static LibGraalFeature singleton() { - // Cannot use ImageSingletons here as it is not initialized early enough. - return singleton; - } - /** * Looks up a class in the libgraal class loader. * @@ -147,30 +114,25 @@ public boolean getAsBoolean() { } } - final LibGraalLoader libgraalLoader = (LibGraalLoader) getClass().getClassLoader(); - - /** - * Set of {@link FeatureComponent}s created during analysis. - */ - private final Set libGraalFeatureComponents = ConcurrentHashMap.newKeySet(); - - public void addFeatureComponent(FeatureComponent fc) { - libGraalFeatureComponents.add(fc); - } + private final LibGraalLoader libgraalLoader = (LibGraalLoader) getClass().getClassLoader(); + private BeforeAnalysisAccess beforeAnalysisAccess; + private BeforeCompilationAccess beforeCompilationAccess; + private OptionCollector optionCollector; @Override public void afterRegistration(AfterRegistrationAccess access) { ImageSingletons.add(NativeBridgeSupport.class, new LibGraalNativeBridgeSupport()); - // The qualified exports from java.base to jdk.internal.vm.ci - // and jdk.graal.compiler need to be expressed as exports to - // ALL-UNNAMED so that access is also possible when these classes - // are loaded via the libgraal loader. - Module javaBase = ModuleLayer.boot().findModule("java.base").orElseThrow(); - Set exports = javaBase.getDescriptor().exports(); - for (ModuleDescriptor.Exports e : exports) { - if (e.targets().contains("jdk.internal.vm.ci") || e.targets().contains("jdk.graal.compiler")) { - Modules.addExportsToAllUnnamed(javaBase, e.source()); + // 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.getModuleMap().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()); + } } } } @@ -178,12 +140,24 @@ public void afterRegistration(AfterRegistrationAccess access) { @Override public void duringSetup(DuringSetupAccess access) { optionCollector = new OptionCollector(); + access.registerObjectReachabilityHandler(optionCollector::accept, OptionKey.class); + access.registerObjectReachabilityHandler(fields -> { + for (int i = 0; i < fields.getOffsets().length; i++) { + Field field = fields.getField(i); + beforeAnalysisAccess.registerAsUnsafeAccessed(field); + } + }, Fields.class); + access.registerObjectReachabilityHandler(nodeClass -> { + Class clazz = nodeClass.getClazz(); + if (!Modifier.isAbstract(clazz.getModifiers())) { + /* Support for NodeClass.allocateInstance. */ + beforeAnalysisAccess.registerAsUnsafeAllocated(clazz); + } + }, NodeClass.class); GetJNIConfig.register((ClassLoader) libgraalLoader); } - private OptionCollector optionCollector; - /** * Collects all instances of the LibGraalLoader loaded {@link OptionKey} class reached by the * static analysis. @@ -223,8 +197,6 @@ void afterAnalysis(AfterAnalysisAccess access) { } } - private BeforeCompilationAccess beforeCompilationAccess; - /** * Transformer for {@code Fields.offsets} and {@code Edges.iterationMask} which need to be * recomputed to use SVM field offsets instead of HotSpot field offsets. @@ -271,14 +243,14 @@ private Map.Entry getReplacement(Object receiver) { private Map.Entry computeReplacement(Object receiver) { Fields fields = (Fields) receiver; - return fields.recomputeOffsetsAndIterationMask(beforeCompilationAccess); + 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 */ @@ -363,13 +335,6 @@ private void doLegacyJVMCIInitialization() { } } - @Override - public void duringAnalysis(DuringAnalysisAccess access) { - for (var c : libGraalFeatureComponents) { - c.duringAnalysis(this, access); - } - } - @Override public void afterAnalysis(AfterAnalysisAccess access) { optionCollector.afterAnalysis(access); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalJNIMethodScope.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalNativeBridgeSupport.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java similarity index 86% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java index a3296a3ec36e..6f6223353c0e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSubstitutions.java @@ -54,4 +54,15 @@ static final class Target_jdk_vm_ci_services_Services { 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..7aeef51cbe24 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalSupportImpl.java @@ -0,0 +1,319 @@ +/* + * 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.Set; +import java.util.function.Supplier; + +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.graal.nativeimage.LibGraalLoader; +import jdk.graal.nativeimage.LibGraalRuntime; +import jdk.graal.nativeimage.hosted.GlobalData; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.hotspot.HotSpotVMConfigStore; + +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; + +/** + * 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 getModuleMap() { + return libGraalLoader.getModuleMap(); + } + + @Platforms(Platform.HOSTED_ONLY.class) + @Override + public Set getServicesModules() { + return libGraalLoader.getServicesModules(); + } + + @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/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/FromLibGraalCalls.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSConsumer.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilable.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilationTask.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerListener.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java similarity index 96% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java index 23ae63f64c30..d2cf241da28f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java @@ -33,6 +33,7 @@ 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; @@ -69,11 +70,12 @@ 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 HSObject implements TruffleCompilerRuntime { +public final class HSTruffleCompilerRuntime extends HSObject implements TruffleCompilerRuntime { static final String COMPILER_VERSION = HotSpotTruffleCompilationSupport.readCompilerVersion(); @@ -246,4 +248,9 @@ public boolean isSuppressedFailure(TruffleCompilable compilable, Supplier id, JNIEnv env) { @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); + // TruffleLibGraalShutdownHook.registerShutdownHook(env, runtimeClass); } catch (Throwable t) { JNIExceptionWrapper.throwInHotSpot(env, t); } @@ -122,6 +123,7 @@ public static long initializeRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadC 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); @@ -322,19 +324,16 @@ 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") + @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 scope = openScope(Id.GetCompilationId, env); - try (JNIMethodScope s = scope) { - CompilationResultInfo compilationResultInfo = LibGraalObjectHandles.resolve(handle, CompilationResultInfo.class); - return compilationResultInfo.getCompilationId(); - } + 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 -1; + return 0; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironment.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java similarity index 88% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java index 2ca597746e75..b062f69c706f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java @@ -27,6 +27,7 @@ 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.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.jniutils.JNI.JClass; @@ -87,10 +88,12 @@ public TruffleHostEnvironment lookup(ResolvedJavaType forType) { * 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. */ - 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; + 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; + } } private static HSTruffleCompilerRuntime hsRuntime(TruffleHostEnvironment environment) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleScopeEntryPoints.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java similarity index 100% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/TruffleFromLibGraalCalls.java 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/common/FeatureComponent.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.java similarity index 50% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.java index 0a2ac2ae1310..169e5a6c61ba 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/FeatureComponent.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/ContextClassLoaderScope.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. * * This code is free software; you can redistribute it and/or modify it @@ -24,17 +24,37 @@ */ package jdk.graal.compiler.core.common; -import org.graalvm.nativeimage.hosted.Feature; - /** - * Implemented by classes that have logic specific to a {@link Feature}s. + * Utility to use in a try-with-resource statement override the + * {@linkplain Thread#getContextClassLoader() context class loader} in a scoped way. */ -public interface FeatureComponent { +public class ContextClassLoaderScope implements AutoCloseable { + private final ClassLoader previous; + private final Thread thread; /** - * Called during analysis of {@code feature}. - * - * @see Feature#duringAnalysis(Feature.DuringAnalysisAccess) + * @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. */ - void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access); + 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 95b443d4c97b..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 @@ -30,19 +30,16 @@ 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.graal.compiler.libgraal.LibGraalFeature; import jdk.internal.misc.Unsafe; -import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.hosted.Feature.BeforeCompilationAccess; /** * Describes fields in a class, primarily for access via {@link Unsafe}. */ -public class Fields implements FeatureComponent { +public class Fields { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final Fields EMPTY_FIELDS = new Fields(Collections.emptyList()); @@ -64,7 +61,6 @@ public class Fields implements FeatureComponent { private final Class[] declaringClasses; - @SuppressWarnings("this-escape") protected Fields(List fields) { Collections.sort(fields); this.offsets = new long[fields.size()]; @@ -79,13 +75,9 @@ protected Fields(List fields) { declaringClasses[index] = f.declaringClass; index++; } - - if (ImageInfo.inImageBuildtimeCode() && LibGraalFeature.singleton() != null) { - LibGraalFeature.singleton().addFeatureComponent(this); - } } - private Field getField(int i) { + public Field getField(int i) { try { return getDeclaringClass(i).getDeclaredField(getName(i)); } catch (NoSuchFieldException e) { @@ -97,31 +89,21 @@ private Field getField(int i) { * Recomputes the {@link Unsafe} based field offsets and the {@link Edges#getIterationMask()} * derived from them. * - * @param access provides the new offsets via {@link BeforeCompilationAccess#objectFieldOffset} + * @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(Feature.BeforeCompilationAccess access) { + 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 = access.objectFieldOffset(field); + long newOffset = getFieldOffset.apply(field); newOffsets[i] = newOffset; } return Map.entry(newOffsets, 0L); } - @Override - public void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access) { - if (feature == LibGraalFeature.singleton()) { - for (int i = 0; i < offsets.length; i++) { - Field field = getField(i); - access.registerAsUnsafeAccessed(field); - } - } - } - public static Fields create(ArrayList fields) { if (fields.isEmpty()) { return EMPTY_FIELDS; 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..7828b2f99260 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java @@ -0,0 +1,187 @@ +/* + * 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 org.graalvm.nativeimage.hosted.RuntimeSystemProperties; + +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.Set; +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 jdk.graal.nativeimage} 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 be used when {@linkplain RuntimeSystemProperties#register registering} properties + * describing the image configuration for libgraal. This is analogous to the configuration info + * displayed by {@code -XshowSettings}. + *

+ * For example: + * + *

+     * RuntimeSystemProperties.register(NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", "serial");
+     * 
+ */ + String NATIVE_IMAGE_SETTING_KEY_PREFIX = "org.graalvm.nativeimage.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 the names of the modules containing classes that can be annotated by + * {@code LibGraalService}. + */ + Set getServicesModules(); + + /** + * 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 compiled into libgraal. + * + * @return an unmodifiable map + */ + Map getModuleMap(); + + /** + * 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. + * + * @return a non-zero value + */ + 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 5bf50c3c9697..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,8 +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; -import jdk.graal.nativeimage.LibGraalRuntime; public class BaseTier extends PhaseSuite { @@ -51,15 +50,16 @@ public LoopPolicies createLoopPolicies(@SuppressWarnings("unused") OptionValues @Override protected void run(StructuredGraph graph, C context) { for (BasePhase phase : getPhases()) { - if (GraalServices.isInLibgraal()) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { /* - * 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. + * 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())) { - LibGraalRuntime.notifyLowMemoryPoint(false); - LibGraalRuntime.processReferences(); + libgraal.notifyLowMemoryPoint(false); + libgraal.processReferences(); } } phase.apply(graph, context); 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 8dd00142c345..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,7 +43,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GraalServices; -import org.graalvm.nativeimage.ImageInfo; final class IgvDumpChannel implements WritableByteChannel { @@ -103,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; 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 0553d368f2ad..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,9 +27,11 @@ 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; @@ -37,7 +39,6 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass.EdgeInfo; import jdk.internal.misc.Unsafe; -import org.graalvm.nativeimage.hosted.Feature; /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the @@ -86,17 +87,16 @@ public enum Type { private final Type type; private final long iterationMask; - @SuppressWarnings("this-escape") public Edges(Type type, int directCount, ArrayList edges) { super(edges); this.type = type; this.directCount = directCount; - this.iterationMask = computeIterationMask(type, directCount, getOffsets()); + this.iterationMask = computeIterationMask(type, directCount, offsets); } @Override - public Map.Entry recomputeOffsetsAndIterationMask(Feature.BeforeCompilationAccess access) { - Map.Entry e = super.recomputeOffsetsAndIterationMask(access); + public Map.Entry recomputeOffsetsAndIterationMask(Function getFieldOffset) { + Map.Entry e = super.recomputeOffsetsAndIterationMask(getFieldOffset); long[] newOffsets = e.getKey(); return Map.entry(newOffsets, computeIterationMask(type, directCount, newOffsets)); } 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 983a60254ca8..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 @@ -47,9 +47,6 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; -import jdk.graal.compiler.libgraal.LibGraalFeature; -import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.graal.compiler.core.common.FeatureComponent; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; @@ -77,10 +74,8 @@ import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodeinfo.Verbosity; import jdk.internal.misc.Unsafe; -import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; /** * Metadata for every {@link Node} type. The metadata includes: @@ -90,7 +85,7 @@ *
  • The identifier for an {@link IterableNodeType} class.
  • * */ -public final class NodeClass extends FieldIntrospection implements FeatureComponent { +public final class NodeClass extends FieldIntrospection { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); // Timers for creation of a NodeClass instance @@ -285,13 +280,6 @@ private NodeClass(Class clazz, NodeClass superNodeClass, FieldsSca debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); } assert verifyMemoryEdgeInvariant(fs) : "Nodes participating in the memory graph should have at most 1 optional memory input."; - - if (ImageInfo.inImageBuildtimeCode() && LibGraalFeature.singleton() != null) { - LibGraalFeature.singleton().addFeatureComponent(this); - } - - // All NodeClass instances must be constructed at libgraal build time - GraalError.guarantee(!GraalServices.isInLibgraal(), getClazz().getName()); } private static boolean verifyMemoryEdgeInvariant(NodeFieldsScanner fs) { @@ -405,16 +393,6 @@ public EnumSet getAllowedUsageTypes() { return allowedUsageTypes; } - @Override - public void duringAnalysis(Feature feature, Feature.DuringAnalysisAccess access) { - if (feature == LibGraalFeature.singleton()) { - if (!Modifier.isAbstract(getClazz().getModifiers())) { - /* Support for NodeClass.allocateInstance. */ - access.registerAsUnsafeAllocated(getClazz()); - } - } - } - /** * Describes a field representing an input or successor edge in a node. */ 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 216311bb7e67..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,12 +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 jdk.graal.nativeimage.LibGraalRuntime; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -64,7 +63,6 @@ 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; @@ -230,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. @@ -489,12 +487,15 @@ public HotSpotCompilationRequestResult runCompilation(OptionValues initialOption public HotSpotCompilationRequestResult runCompilation(DebugContext debug) { try (DebugCloseable a = CompilationTime.start(debug)) { HotSpotCompilationRequestResult result = runCompilation(debug, new HotSpotCompilationWrapper()); - if (GraalServices.isInLibgraal()) { - // Notify the runtime that most objects allocated in the current compilation - // are dead and can be reclaimed. + 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)) { - LibGraalRuntime.notifyLowMemoryPoint(true); - LibGraalRuntime.processReferences(); + libgraal.notifyLowMemoryPoint(true); + libgraal.processReferences(); } } return result; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java similarity index 94% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java index 168a093c8302..12f78be1949a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.libgraal; +package jdk.graal.compiler.hotspot; import java.io.FileOutputStream; import java.io.PrintStream; @@ -39,12 +39,6 @@ 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; 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 20877b77eb81..1ef39a477e73 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,7 +25,7 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static jdk.graal.compiler.libgraal.LibGraalFeature.NATIVE_IMAGE_SETTING_KEY_PREFIX; +import static jdk.graal.compiler.core.common.LibGraalSupport.NATIVE_IMAGE_SETTING_KEY_PREFIX; import java.util.ArrayList; import java.util.Collections; 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 83088874ec8f..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 @@ -37,6 +37,7 @@ 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; @@ -47,7 +48,6 @@ import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.phases.OnStackReplacementPhase; import jdk.graal.compiler.java.GraphBuilderPhase; -import jdk.graal.compiler.libgraal.LibGraalJNIMethodScope; import jdk.graal.compiler.lir.asm.CompilationResultBuilderFactory; import jdk.graal.compiler.lir.phases.LIRSuites; import jdk.graal.compiler.nodes.Cancellable; @@ -65,8 +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.word.Word; -import jdk.graal.nativeimage.LibGraalRuntime; import jdk.internal.misc.Unsafe; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; @@ -80,9 +78,6 @@ import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; import jdk.vm.ci.runtime.JVMCICompiler; -import org.graalvm.jniutils.JNI; -import org.graalvm.jniutils.JNIMethodScope; -import org.graalvm.nativeimage.ImageInfo; public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable, JVMCICompilerShadow, GraalCompiler.RequestedCrashHandler { @@ -130,52 +125,13 @@ public HotSpotGraalRuntimeProvider getGraalRuntime() { return graalRuntime; } - /** - * 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(HotSpotGraalRuntime.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. - */ - HotSpotGraalRuntime.doReferenceHandling(); - } - } - } - @SuppressWarnings("try") @Override public CompilationRequestResult compileMethod(CompilationRequest request) { - try (AutoCloseable ignored = ImageInfo.inImageRuntimeCode() ? new LibGraalCompilationRequestScope() : null) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { return compileMethod(request, true, getGraalRuntime().getOptions()); } catch (Exception e) { - e.printStackTrace(System.out); return HotSpotCompilationRequestResult.failure(e.toString(), false); } } @@ -205,10 +161,11 @@ 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; - ThreadFactory factory = ImageInfo.inImageRuntimeCode() ? HotSpotGraalServiceThread::new : null; + 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);) { @@ -418,7 +375,8 @@ public boolean isGCSupported(int gcIdentifier) { @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 @@ -437,7 +395,7 @@ public boolean notifyCrash(OptionValues options, String crashMessage) { } catch (InterruptedException e) { // ignore } - LibGraalRuntime.fatalError(crashMessage); + 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/HotSpotGraalOptionValues.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java index 1da599ea8cfd..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,11 +27,9 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.io.PrintStream; -import java.util.Comparator; -import java.util.List; 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; @@ -43,9 +41,6 @@ import jdk.vm.ci.common.InitTimer; import org.graalvm.collections.EconomicSet; -import org.graalvm.collections.MapCursor; -import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.nativeimage.RuntimeOptions; /** * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The @@ -72,8 +67,6 @@ 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. */ @@ -142,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; @@ -170,38 +159,6 @@ private static String stripPrefix(String name, String prefix) { return baseName; } - /** - * @param settings unparsed libgraal option values - */ - private static void notifyLibgraalOptions(EconomicMap settings) { - if (ImageInfo.inImageRuntimeCode()) { - 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); - } - } - } else { - System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", settings.toString()); - } - } - /** * The set of libgraal options seen on the command line. */ @@ -219,21 +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 && ImageInfo.inImageRuntimeCode()) { - if (ImageInfo.inImageRuntimeCode()) { - Comparator comparator = Comparator.comparing(RuntimeOptions.Descriptor::name); - RuntimeOptions.listDescriptors().stream().sorted(comparator).forEach(d -> { - String assign = explicitOptions.contains(d.name()) ? ":=" : "="; - OptionValues.printHelp(out, LIBGRAAL_VM_OPTION_PROPERTY_PREFIX, - d.name(), - RuntimeOptions.get(d.name()), - d.valueType(), - assign, - "[community edition]", - d.help(), - List.of()); - }); - } + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (all && libgraal != null) { + libgraal.printOptions(out, LIBGRAAL_VM_OPTION_PROPERTY_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 11052d7c19c3..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,16 +35,7 @@ import java.util.Map; import java.util.function.Predicate; -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.TargetClass; -import jdk.graal.compiler.libgraal.LibGraalFeature; -import jdk.graal.compiler.word.Word; -import jdk.graal.nativeimage.LibGraalRuntime; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import org.graalvm.jniutils.JNI; -import org.graalvm.jniutils.JNIExceptionWrapper; -import org.graalvm.jniutils.JNIUtil; -import org.graalvm.nativeimage.ImageInfo; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; @@ -84,8 +75,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.runtime.JVMCIBackend; -import org.graalvm.nativeimage.StackValue; -import org.graalvm.nativeimage.VMRuntime; //JaCoCo Exclude @@ -110,31 +99,6 @@ private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAcc private final String compilerConfigurationName; private final HotSpotBackend hostBackend; - /** - * 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. - */ - Target_jdk_vm_ci_hotspot_Cleaner.clean(); - } - - @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(); - } - public GlobalMetrics getMetricValues() { return metricValues; } @@ -229,8 +193,9 @@ public GlobalMetrics getMetricValues() { this.compilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); - if (ImageInfo.inImageRuntimeCode()) { - VMRuntime.initialize(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + libgraal.initialize(); } } @@ -457,48 +422,21 @@ 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); - - JNI.JNIEnv env = Word.unsigned(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); - + callbackClassName = callback.substring(0, lastDot); + callbackMethodName = callback.substring(lastDot + 1); } - VMRuntime.shutdown(); - } - } - - 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"); + libgraal.shutdown(callbackClassName, callbackMethodName); } - 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; } void clearMetrics() { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java deleted file mode 100644 index 4009f66f5972..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/libgraal/truffle/TruffleLibGraalShutdownHook.java +++ /dev/null @@ -1,78 +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.libgraal.truffle; - -import com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal; -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 org.graalvm.jniutils.JNI.JClass; -import org.graalvm.jniutils.JNI.JNIEnv; -import org.graalvm.jniutils.JNI.JavaVM; -import org.graalvm.jniutils.JNIUtil; - -import static com.oracle.truffle.compiler.hotspot.libgraal.TruffleFromLibGraal.Id.OnIsolateShutdown; - -@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(JNIEnv env, JClass runtimeClass) { - JavaVM vm = JNIUtil.GetJavaVM(env); - ShutdownHook hook = registeredHook; - assert hook == null || hook.javaVm.isNull() || hook.javaVm.equal(vm); - registeredHook = new ShutdownHook(vm, new TruffleFromLibGraalCalls(env, runtimeClass)); - } - - static class ShutdownHook implements HotSpotVMEventListener { - - private final JavaVM javaVm; - private final TruffleFromLibGraalCalls calls; - - ShutdownHook(JavaVM javaVm, TruffleFromLibGraalCalls calls) { - this.javaVm = javaVm; - this.calls = calls; - } - - @Override - @TruffleFromLibGraal(OnIsolateShutdown) - public void notifyShutdown() { - JNIEnv env = JNIUtil.GetEnv(javaVm); - assert env.isNonNull(); - TruffleLibGraalShutdownHookGen.callOnIsolateShutdown(calls, env, IsolateUtil.getIsolateID()); - } - } -} 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 c2e15a554168..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,13 +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.graal.nativeimage.LibGraalRuntime; import jdk.vm.ci.code.TargetDescription; public class LIRPhaseSuite extends LIRPhase implements PhasePlan> { @@ -106,14 +105,16 @@ public static boolean findNextPhase(ListIterator> it, Class phase : phases) { - if (GraalServices.isInLibgraal()) { - // 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. + 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())) { - LibGraalRuntime.notifyLowMemoryPoint(false); - LibGraalRuntime.processReferences(); + 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 d8016300ffb2..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 @@ -93,7 +93,6 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re return false; } - ResolvedJavaMethod thisExecuteMethod = getExecuteMethod(b); if (inImageBuildtimeCode()) { // Calls to the @Fold method from the generated fold plugin shouldn't be folded. This is // detected by comparing the class names of the current plugin and the method being @@ -106,6 +105,7 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re } } + ResolvedJavaMethod thisExecuteMethod = getExecuteMethod(b); if (b.getMethod().equals(thisExecuteMethod)) { return true; } 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 3640ddf592b4..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,11 +38,10 @@ import java.util.function.Function; import java.util.regex.Pattern; -import jdk.graal.nativeimage.LibGraalLoader; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; -import org.graalvm.nativeimage.ImageInfo; /** * This class contains methods for parsing Graal options and matching them against a set of @@ -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 a - * {@link jdk.graal.nativeimage.LibGraalLoader}. + * 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,12 +63,9 @@ public static LibGraalOptionsInfo create() { } /** - * Compiler options info available in libgraal. This field is only non-null when - * {@link OptionsParser} is loaded by a {@link jdk.graal.nativeimage.LibGraalLoader} and - * {@linkplain ImageInfo#inImageBuildtimeCode libgraal is being built}. + * Compiler options info available in libgraal. */ - public static final LibGraalOptionsInfo libgraalOptions = inImageBuildtimeCode() && - OptionsParser.class.getClassLoader() instanceof LibGraalLoader ? LibGraalOptionsInfo.create() : null; + public static final LibGraalOptionsInfo libgraalOptions = LibGraalSupport.inLibGraal() ? LibGraalOptionsInfo.create() : null; /** * Gets an iterable of available {@link OptionDescriptors}. @@ -82,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) { + if (LibGraalSupport.inLibGraal()) { /* - * Graal code being run is loaded by a LibGraalLoader while building libgraal so use the - * loader 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); 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 089c0807c6a7..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 @@ -28,9 +28,8 @@ 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.graal.nativeimage.LibGraalLoader; -import jdk.graal.nativeimage.hosted.GlobalData; import jdk.internal.misc.Unsafe; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.Platform; @@ -49,7 +48,7 @@ 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; @@ -66,8 +65,7 @@ public class GlobalAtomicLong { private volatile long address; /** - * Supplies the address of the global memory storing the global value. This field is transformed - * during native image building into a supplier backed by {@link GlobalData} + * Supplies the address of the global memory storing the global value. */ private final Supplier addressSupplier; @@ -87,13 +85,15 @@ public GlobalAtomicLong(String name, long initialValue) { if (ImageInfo.inImageRuntimeCode()) { throw GraalError.shouldNotReachHere("Cannot create " + getClass().getName() + " objects in native image runtime"); } else { - if (ImageInfo.inImageBuildtimeCode() && GlobalAtomicLong.class.getClassLoader() instanceof LibGraalLoader) { - addressSupplier = GlobalData.createGlobal(initialValue); + 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 = () -> { - if (ImageInfo.inImageRuntimeCode()) { - throw GraalError.shouldNotReachHere("The addressSupplier field value should have been replaced at image build time"); - } long addr = UNSAFE.allocateMemory(Long.BYTES); synchronized (GlobalAtomicLong.class) { if (cleaner == null) { 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 f30eca33ff76..b78cfb2f7d35 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 @@ -41,7 +41,7 @@ import java.util.Set; import jdk.graal.compiler.core.ArchitectureSpecific; -import jdk.graal.nativeimage.LibGraalLoader; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.vm.ci.code.Architecture; import org.graalvm.nativeimage.ImageInfo; @@ -60,17 +60,16 @@ public final class GraalServices { /** - * 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. + * 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 isInLibgraal() { return Services.IS_IN_NATIVE_IMAGE; } /** - * The set of services available in libgraal. This field is only non-null when - * {@link GraalServices} is loaded by a {@link LibGraalLoader}. + * The set of services available in libgraal. */ private static final Map, List> libgraalServices; @@ -113,11 +112,11 @@ private static void addProviders(String arch, Class service) { } static { - ClassLoader cl = GraalServices.class.getClassLoader(); - if (inImageBuildtimeCode() && cl instanceof LibGraalLoader libgraalLoader) { + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { libgraalServices = new HashMap<>(); - Set libgraalServicesModules = libgraalLoader.getServicesModules(); - Map modules = libgraalLoader.getModuleMap(); + Set libgraalServicesModules = libgraal.getServicesModules(); + Map modules = libgraal.getModuleMap(); String arch = getJVMCIArch(); modules.entrySet().stream()// .filter(e -> libgraalServicesModules.contains(e.getValue()))// 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 854b40dec5c7..2e8218f2f547 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,9 +24,7 @@ */ package jdk.graal.compiler.serviceprovider; -import jdk.graal.nativeimage.LibGraalRuntime; -import org.graalvm.nativeimage.CurrentIsolate; -import org.graalvm.nativeimage.ImageInfo; +import jdk.graal.compiler.core.common.LibGraalSupport; /** * Utility methods that provide access to isolate details. @@ -37,8 +35,9 @@ public final class IsolateUtil { * Gets the address of the current isolate or 0 if this not an isolate-aware runtime. */ public static long getIsolateAddress() { - if (ImageInfo.inImageRuntimeCode()) { - return CurrentIsolate.getIsolate().rawValue(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + return libgraal.getIsolateAddress(); } return 0L; } @@ -49,8 +48,9 @@ public static long getIsolateAddress() { * process. */ public static long getIsolateID() { - if (ImageInfo.inImageRuntimeCode()) { - return LibGraalRuntime.getIsolateID(); + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + if (libgraal != null) { + return libgraal.getIsolateID(); } return 0L; } diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java index a75d5753ce43..803e7859055d 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.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. * * This code is free software; you can redistribute it and/or modify it diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java index 435a53be6018..4aed3b07f5a9 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.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. * * This code is free software; you can redistribute it and/or modify it @@ -72,9 +72,7 @@ public static long getIsolateID() { /** * Called to signal a fatal, non-recoverable error. This method does not return or throw an - * exception. A typical implementation will delegate to an OS function that kills the process. - * In the context of libgraal, it will call the HotSpot fatal crash routine that produces an - * hs-err crash log. + * exception but calls the HotSpot fatal crash routine that produces an hs-err crash log. * * @param message a description of the error condition */ diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java index c7f9506b3e17..04dace216222 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.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. * * This code is free software; you can redistribute it and/or modify it diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java index 1e1308db26d3..3d8084d561d9 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java @@ -24,9 +24,17 @@ */ package jdk.graal.nativeimage.impl; +import jdk.graal.nativeimage.hosted.GlobalData; + import java.util.function.Supplier; +/** + * Service provider interface for implementation of {@link GlobalData}. + */ public interface GlobalDataSupport { + /** + * @see GlobalData#createGlobal(long) + */ Supplier createGlobal(long initialValue); } diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java index d8572ce02120..609c82c7724f 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.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. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,30 @@ */ package jdk.graal.nativeimage.impl; +import jdk.graal.nativeimage.LibGraalRuntime; + +/** + * Service provider interface for implementation of {@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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java index c0f173932130..c79f092d95cb 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java +++ b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.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. * * This code is free software; you can redistribute it and/or modify it diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 7bb74bd70391..a32522b0c59b 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -143,13 +143,7 @@ def upx(args): third_party_license_files=[], dependencies=[], jar_distributions=[], - boot_jars=[ - 'sdk:WORD', - 'sdk:COLLECTIONS', - 'sdk:NATIVEIMAGE', - 'sdk:NATIVEBRIDGE', - 'sdk:JNIUTILS' - ], + boot_jars=['sdk:WORD', 'sdk:COLLECTIONS', 'sdk:NATIVEIMAGE'], stability="supported", ) mx_sdk_vm.register_graalvm_component(graal_sdk_compiler_component) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index f655740cc70b..551ceff88ae3 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -1471,9 +1471,13 @@ 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', 'compiler:LIBGRAAL_LOADER'] def allow_build_path_in_libgraal(): @@ -1523,6 +1527,7 @@ def prevent_build_path_in_libgraal(): 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=', diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index a246a875b0b9..098b92945d15 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -220,6 +220,7 @@ "dependencies": [ "sdk:NATIVEIMAGE", "compiler:GRAAL", + "compiler:GRAAL_NATIVEIMAGE", ], "requiresConcealed" : { "java.base" : ["jdk.internal.module"], @@ -2142,6 +2143,7 @@ ], "distDependencies": [ "compiler:GRAAL", + "compiler:GRAAL_NATIVEIMAGE", "sdk:NATIVEIMAGE", ], "exclude": [ 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 5a9019b31503..e38bd4a27ce7 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,7 +28,7 @@ import java.util.List; import java.util.Map; -import jdk.graal.compiler.libgraal.LibGraalFeature; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -132,7 +132,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { } String gcName = Heap.getHeap().getGC().getName(); - RuntimeSystemProperties.register(LibGraalFeature.NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", gcName); + RuntimeSystemProperties.register(LibGraalSupport.NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", gcName); // Needed for the barrier set. access.registerAsUsed(Object[].class); 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 bb2e20200d05..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 @@ -209,7 +209,7 @@ private static Field findField(Fields fields, int index) { @Override public void beforeCompilation(BeforeCompilationAccess a) { for (FieldsOffsetsReplacement replacement : getReplacements().values()) { - Map.Entry e = replacement.fields.recomputeOffsetsAndIterationMask(a); + Map.Entry e = replacement.fields.recomputeOffsetsAndIterationMask(a::objectFieldOffset); replacement.newOffsets = e.getKey(); replacement.newIterationInitMask = e.getValue(); } 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 f6991a0e8ff5..2dc212f2e769 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,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import jdk.graal.compiler.core.common.ContextClassLoaderScope; import jdk.graal.nativeimage.LibGraalLoader; import org.graalvm.collections.EconomicSet; import org.graalvm.nativeimage.ImageSingletons; @@ -189,18 +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) { LibGraalLoader libGraalLoader = loader.classLoaderSupport.getLibGraalLoader(); - Thread thread = Thread.currentThread(); - ClassLoader restoreCCL = null; - ClassLoader clazzLoader = clazz.getClassLoader(); - if (libGraalLoader != null && (ClassLoader) libGraalLoader == clazzLoader) { - // Graal and JVMCI make use of ServiceLoader which uses the - // context class loader so it needs to be the libgraal loader. - restoreCCL = thread.getContextClassLoader(); - thread.setContextClassLoader(clazz.getClassLoader()); - } - try { + 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 @@ -245,10 +242,6 @@ InitKind ensureClassInitialized(Class clazz, boolean allowErrors) { throw UserError.abort(t, "%s", msg); } - } finally { - if (restoreCCL != null) { - thread.setContextClassLoader(restoreCCL); - } } } 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 6866faf10671..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 @@ -324,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; } From 4880899a6cb4509bedcbcd38c17cfca91cfea5e0 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sat, 8 Feb 2025 15:50:17 +0100 Subject: [PATCH 4/9] moved jdk.graal.nativeimage to sdk --- compiler/mx.compiler/suite.py | 45 +---------- .../jdk/graal/nativeimage/LibGraalLoader.java | 65 --------------- .../graal/nativeimage/hosted/GlobalData.java | 54 ------------- .../nativeimage/hosted/package-info.java | 35 -------- .../nativeimage/impl/GlobalDataSupport.java | 40 --------- .../impl/LibGraalRuntimeSupport.java | 53 ------------ .../jdk/graal/nativeimage/package-info.java | 35 -------- sdk/mx.sdk/mx_sdk.py | 2 +- sdk/mx.sdk/suite.py | 38 +++++++++ .../jdk.graal.nativeimage/snapshot.sigtest | 5 +- .../jdk/graal/nativeimage/LibGraalLoader.java | 81 +++++++++++++++++++ .../graal/nativeimage/LibGraalRuntime.java | 48 +++++++---- .../graal/nativeimage/hosted/GlobalData.java | 70 ++++++++++++++++ .../nativeimage/hosted/package-info.java | 51 ++++++++++++ .../nativeimage/impl/GlobalDataSupport.java | 56 +++++++++++++ .../impl/LibGraalRuntimeSupport.java | 69 ++++++++++++++++ .../jdk/graal/nativeimage/package-info.java | 51 ++++++++++++ substratevm/mx.substratevm/suite.py | 4 +- 18 files changed, 456 insertions(+), 346 deletions(-) delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java delete mode 100644 compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java rename {compiler => sdk}/src/jdk.graal.nativeimage/snapshot.sigtest (84%) create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java rename {compiler => sdk}/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java (55%) create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java create mode 100644 sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 5e1cbda6ffd9..edcd40e3a381 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -473,17 +473,6 @@ # ------------- libgraal ------------- - # Native Image API extensions for libgraal. - "jdk.graal.nativeimage" : { - "subDir" : "src", - "sourceDirs" : ["src"], - "dependencies" : [ - "sdk:NATIVEIMAGE" - ], - "checkstyle" : "jdk.graal.compiler", - "javaCompliance" : "21+" - }, - # 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 @@ -495,7 +484,7 @@ "javaCompliance" : "21+", "dependencies" : [ "GRAAL", - "GRAAL_NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", "sdk:JNIUTILS", "sdk:NATIVEBRIDGE" ], @@ -523,7 +512,7 @@ "workingSets" : "Graal", "javaCompliance" : "21+", "dependencies" : [ - "GRAAL_NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", ], "requiresConcealed" : { "java.base" : [ @@ -681,39 +670,13 @@ }, }, - "GRAAL_NATIVEIMAGE" : { - "subDir" : "src", - "dependencies" : [ - "jdk.graal.nativeimage", - ], - "distDependencies" : ["sdk:NATIVEIMAGE"], - "javadocType": "api", - "moduleInfo" : { - "name" : "jdk.graal.nativeimage", - "requires" : [ - "transitive org.graalvm.nativeimage", - ], - "exports" : [ - "jdk.graal.nativeimage", - "jdk.graal.nativeimage.hosted", - "jdk.graal.nativeimage.impl to org.graalvm.nativeimage.builder", - ], - "uses" : [], - "opens" : [], - }, - "description" : "Native Image API extensions for libgraal.", - "maven": { - "tag": ["default", "public"], - }, - }, - "LIBGRAAL_LOADER" : { "subDir": "src", "dependencies" : [ "jdk.graal.compiler.libgraal.loader" ], "distDependencies" : [ - "GRAAL_NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", "GRAAL", ], "maven": False, @@ -731,7 +694,7 @@ ], "distDependencies": [ "GRAAL", - "GRAAL_NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", "sdk:JNIUTILS", "sdk:NATIVEIMAGE", "sdk:NATIVEBRIDGE" diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java deleted file mode 100644 index 803e7859055d..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.nativeimage; - -import java.nio.file.Path; -import java.util.Map; -import java.util.Set; - -/** - * 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 the {@code java.home} of the JDK whose runtime image contains the Graal and JVMCI - * classes from which libgraal will be built. - */ - Path getJavaHome(); - - /** - * Gets the ClassLoader that should be seen at image runtime if a class was loaded at image - * build-time by this loader. - */ - ClassLoader getRuntimeClassLoader(); - - /** - * 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 getModuleMap(); - - /** - * Gets the names of the modules containing classes that can be annotated by - * {@code LibGraalService}. - */ - Set getServicesModules(); -} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java deleted file mode 100644 index 3f87d8dd9338..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.nativeimage.hosted; - -import jdk.graal.nativeimage.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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java deleted file mode 100644 index 04dace216222..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ -/* - @ApiInfo( - group="Native Image LibGraal extensions" - ) - */ -/** - * Extensions to the GraalVM SDK Native Image API to customize building libgraal. - * - * @since 25 - */ -package jdk.graal.nativeimage.hosted; diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java deleted file mode 100644 index 3d8084d561d9..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.nativeimage.impl; - -import jdk.graal.nativeimage.hosted.GlobalData; - -import java.util.function.Supplier; - -/** - * Service provider interface for implementation of {@link GlobalData}. - */ -public interface GlobalDataSupport { - - /** - * @see GlobalData#createGlobal(long) - */ - Supplier createGlobal(long initialValue); -} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java deleted file mode 100644 index 609c82c7724f..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.nativeimage.impl; - -import jdk.graal.nativeimage.LibGraalRuntime; - -/** - * Service provider interface for implementation of {@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/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java b/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java deleted file mode 100644 index c79f092d95cb..000000000000 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ -/* - @ApiInfo( - group="Native Image LibGraal extensions" - ) - */ -/** - * Extensions to the GraalVM SDK Native Image API to customize building libgraal. - * - * @since 25 - */ -package jdk.graal.nativeimage; diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index a32522b0c59b..090205802b86 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -158,7 +158,7 @@ def upx(args): third_party_license_files=[], dependencies=['sdkc'], jar_distributions=[], - boot_jars=['sdk:NATIVEIMAGE', 'compiler:GRAAL_NATIVEIMAGE'], + boot_jars=['sdk:NATIVEIMAGE', 'sdk:GRAAL_NATIVEIMAGE'], 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..44627956b91c 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. + "jdk.graal.nativeimage" : { + "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 { }, }, + "GRAAL_NATIVEIMAGE" : { + "subDir" : "src", + "dependencies" : [ + "jdk.graal.nativeimage", + ], + "distDependencies" : ["NATIVEIMAGE"], + "javadocType": "api", + "moduleInfo" : { + "name" : "jdk.graal.nativeimage", + "requires" : [ + "transitive org.graalvm.nativeimage", + ], + "exports" : [ + "jdk.graal.nativeimage", + "jdk.graal.nativeimage.hosted", + "jdk.graal.nativeimage.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/compiler/src/jdk.graal.nativeimage/snapshot.sigtest b/sdk/src/jdk.graal.nativeimage/snapshot.sigtest similarity index 84% rename from compiler/src/jdk.graal.nativeimage/snapshot.sigtest rename to sdk/src/jdk.graal.nativeimage/snapshot.sigtest index 1456a58e38cc..98f6e42a9942 100644 --- a/compiler/src/jdk.graal.nativeimage/snapshot.sigtest +++ b/sdk/src/jdk.graal.nativeimage/snapshot.sigtest @@ -2,10 +2,7 @@ #Version CLSS public abstract interface jdk.graal.nativeimage.LibGraalLoader -meth public abstract java.nio.file.Path getJavaHome() -meth public abstract java.util.Set getServicesModules() -meth public abstract java.lang.ClassLoader getRuntimeClassLoader() -meth public abstract java.util.Map getModuleMap() +meth public abstract java.util.Map getClassModuleMap() CLSS public final jdk.graal.nativeimage.LibGraalRuntime meth public static long getIsolateID() diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java new file mode 100644 index 000000000000..048d54c97be2 --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java @@ -0,0 +1,81 @@ +/* + * 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 jdk.graal.nativeimage; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; + +/** + * 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 the {@code java.home} of the JDK whose runtime image contains the Graal and JVMCI + * classes from which libgraal will be built. + */ + Path getJavaHome(); + + /** + * Gets the ClassLoader that should be seen at image runtime if a class was loaded at image + * build-time by this loader. + */ + ClassLoader getRuntimeClassLoader(); + + /** + * 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 getModuleMap(); + + /** + * Gets the names of the modules containing classes that can be annotated by + * {@code LibGraalService}. + */ + Set getServicesModules(); +} diff --git a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java similarity index 55% rename from compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java rename to sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java index 4aed3b07f5a9..ea2c782ce5b6 100644 --- a/compiler/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java @@ -2,25 +2,41 @@ * 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. + * The Universal Permissive License (UPL), Version 1.0 * - * 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). + * 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 * - * 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. + * (a) the Software, and * - * 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. + * (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 jdk.graal.nativeimage; diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java new file mode 100644 index 000000000000..40fdba2f13f7 --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/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 jdk.graal.nativeimage.hosted; + +import jdk.graal.nativeimage.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/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java new file mode 100644 index 000000000000..2c6bd106abcc --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java @@ -0,0 +1,51 @@ +/* + * 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. + * + * @since 25 + */ +package jdk.graal.nativeimage.hosted; diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java new file mode 100644 index 000000000000..a78bad798e08 --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/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 jdk.graal.nativeimage.impl; + +import jdk.graal.nativeimage.hosted.GlobalData; + +import java.util.function.Supplier; + +/** + * Service provider interface for implementation of {@link GlobalData}. + */ +public interface GlobalDataSupport { + + /** + * @see GlobalData#createGlobal(long) + */ + Supplier createGlobal(long initialValue); +} diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java new file mode 100644 index 000000000000..bfd3639bd43a --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/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 jdk.graal.nativeimage.impl; + +import jdk.graal.nativeimage.LibGraalRuntime; + +/** + * Service provider interface for implementation of {@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/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java new file mode 100644 index 000000000000..33dc85dd0427 --- /dev/null +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java @@ -0,0 +1,51 @@ +/* + * 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. + * + * @since 25 + */ +package jdk.graal.nativeimage; diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 098b92945d15..93b04a09bc59 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -219,8 +219,8 @@ "sourceDirs": ["src"], "dependencies": [ "sdk:NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", "compiler:GRAAL", - "compiler:GRAAL_NATIVEIMAGE", ], "requiresConcealed" : { "java.base" : ["jdk.internal.module"], @@ -2143,8 +2143,8 @@ ], "distDependencies": [ "compiler:GRAAL", - "compiler:GRAAL_NATIVEIMAGE", "sdk:NATIVEIMAGE", + "sdk:GRAAL_NATIVEIMAGE", ], "exclude": [ ], From 9ec1aec57beb9bf305a6897750002c2f73240315 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sun, 9 Feb 2025 22:47:34 +0100 Subject: [PATCH 5/9] reduced LibGraalLoader API * renamed LibGraalLoader.getModuleMap to getClassModuleMap * replaced LibGraalLoader.getJavaHome with a protocol shared between HostedLibGraalClassLoader and LibGraalFeature * removed LibGraalLoader.getRuntimeClassLoader * remove LibGraalLoader.getServiceModules --- .../loader/HostedLibGraalClassLoader.java | 65 ++++++++++--------- .../graal/compiler/libgraal/GetJNIConfig.java | 8 +-- .../libgraal}/LibGraalClassLoader.java | 15 ++--- .../compiler/libgraal/LibGraalFeature.java | 46 +++++++++++-- .../libgraal/LibGraalSupportImpl.java | 11 +--- .../compiler/core/common/LibGraalSupport.java | 12 +--- .../serviceprovider/GraalServices.java | 7 +- .../jdk/graal/nativeimage/LibGraalLoader.java | 22 +------ .../oracle/svm/hosted/ClassLoaderFeature.java | 9 --- .../hosted/NativeImageClassLoaderSupport.java | 2 +- 10 files changed, 91 insertions(+), 106 deletions(-) rename compiler/src/{jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader => jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal}/LibGraalClassLoader.java (74%) diff --git a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java index 87d1828f03d3..2cc09d6b2038 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java +++ b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java @@ -57,12 +57,12 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; /** * A classloader that reads class files and resources from a jimage file and a module path at image - * build time. + * 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. */ @Platforms(Platform.HOSTED_ONLY.class) public final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalLoader { @@ -73,6 +73,12 @@ public final class HostedLibGraalClassLoader extends ClassLoader implements LibG */ 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. @@ -167,30 +173,17 @@ byte[] readBytes() throws ClassNotFoundException { /** * Modules containing classes that can be annotated by {@code LibGraalService}. */ - private static final Set LIBGRAAL_SERVICES_MODULES = Set.of( + private static final Set LIBGRAAL_MODULES = Set.of( + "jdk.internal.vm.ci", "jdk.graal.compiler", "jdk.graal.compiler.libgraal", "org.graalvm.truffle.compiler", "com.oracle.graal.graal_enterprise"); - /** - * Modules in which Graal and JVMCI classes are defined that this loader will load. - */ - private static final Set LIBGRAAL_MODULES = Stream.concat( - LIBGRAAL_SERVICES_MODULES.stream(), Stream.of("jdk.internal.vm.ci")) // - .collect(Collectors.toUnmodifiableSet()); - static { ClassLoader.registerAsParallelCapable(); } - private final Path libgraalJavaHome = Path.of(System.getProperty(LIBGRAAL_JAVA_HOME_PROPERTY_NAME, System.getProperty("java.home"))); - - @Override - public Path getJavaHome() { - return libgraalJavaHome; - } - /** * Converts the module path entry {@code s} to a {@link Path}. * @@ -207,7 +200,7 @@ Path parseModulePathEntry(String s) { @SuppressWarnings("unused") public HostedLibGraalClassLoader() { // This loader delegates to the class loader that loaded its own class. - super(LibGraalClassLoader.LOADER_NAME, HostedLibGraalClassLoader.class.getClassLoader()); + super("LibGraalClassLoader", HostedLibGraalClassLoader.class.getClassLoader()); try { /* @@ -226,7 +219,7 @@ public HostedLibGraalClassLoader() { Map modulesMap = 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); @@ -286,15 +279,10 @@ public HostedLibGraalClassLoader() { * name of its enclosing module. */ @Override - public Map getModuleMap() { + public Map getClassModuleMap() { return modules; } - @Override - public Set getServicesModules() { - return LIBGRAAL_SERVICES_MODULES; - } - @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (!modules.containsKey(name)) { @@ -328,6 +316,12 @@ protected Class findClass(final String name) throws ClassNotFoundException { */ 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}. */ @@ -341,7 +335,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 { @@ -382,7 +383,12 @@ 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()); @@ -434,9 +440,4 @@ public String getContentType() { return "application/octet-stream"; } } - - @Override - public ClassLoader getRuntimeClassLoader() { - return LibGraalClassLoader.singleton; - } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java index 7c36396663e0..8485c6a82822 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/GetJNIConfig.java @@ -78,9 +78,9 @@ 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(GraalServices.getSavedProperty("java.home"))); + Path javaExe = getJavaExe(libgraalJavaHome); configFilePath = Path.of("libgraal_jniconfig.txt"); String[] command = {javaExe.toFile().getAbsolutePath(), "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-XX:JVMCILibDumpJNIConfig=" + configFilePath}; @@ -196,8 +196,8 @@ private GraalError error(String format, Object... args) { * @param loader used to resolve type names in the config */ @SuppressWarnings("try") - public static void register(ClassLoader loader) { - 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++; diff --git a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.java similarity index 74% rename from compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java rename to compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.java index 90df8b485bbe..f47fe441b156 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/LibGraalClassLoader.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalClassLoader.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. * * This code is free software; you can redistribute it and/or modify it @@ -22,20 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.graal.compiler.libgraal.loader; +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 {@link HostedLibGraalClassLoader}. + * replaces} the build-time instance of the {@link jdk.graal.nativeimage.LibGraalLoader}. */ -public final class LibGraalClassLoader extends ClassLoader { +final class LibGraalClassLoader extends ClassLoader { - static final String LOADER_NAME = "LibGraalClassLoader"; - static final LibGraalClassLoader singleton = new LibGraalClassLoader(); - - private LibGraalClassLoader() { - super(LOADER_NAME, null); + LibGraalClassLoader(String name) { + super(name, null); } } 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 index 74b2d60dd618..f0718f7fc4a7 100644 --- 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 @@ -24,6 +24,8 @@ */ 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; @@ -114,7 +116,23 @@ public boolean getAsBoolean() { } } + /** + * 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; @@ -126,7 +144,7 @@ public void afterRegistration(AfterRegistrationAccess access) { // 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.getModuleMap().values()); + Set libgraalModules = Set.copyOf(libgraalLoader.getClassModuleMap().values()); for (Module module : ModuleLayer.boot().modules()) { Set exports = module.getDescriptor().exports(); for (ModuleDescriptor.Exports e : exports) { @@ -141,13 +159,28 @@ public void afterRegistration(AfterRegistrationAccess access) { 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())) { @@ -155,12 +188,14 @@ public void duringSetup(DuringSetupAccess access) { beforeAnalysisAccess.registerAsUnsafeAllocated(clazz); } }, NodeClass.class); - GetJNIConfig.register((ClassLoader) libgraalLoader); + + // 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. + * static analysis and uses them to initialize {@link OptionsParser#libgraalOptions}. */ private final class OptionCollector implements Consumer> { private final Set> options = Collections.newSetFromMap(new ConcurrentHashMap<>()); @@ -178,7 +213,7 @@ public void accept(OptionKey option) { void afterAnalysis(AfterAnalysisAccess access) { sealed = true; - Map modules = libgraalLoader.getModuleMap(); + Map modules = libgraalLoader.getClassModuleMap(); for (OptionKey option : options) { OptionDescriptor descriptor = option.getDescriptor(); if (descriptor.isServiceLoaded()) { @@ -272,8 +307,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { doLegacyJVMCIInitialization(); - Path libGraalJavaHome = libgraalLoader.getJavaHome(); - GetCompilerConfig.Result configResult = GetCompilerConfig.from(libGraalJavaHome); + 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()) { 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 index 7aeef51cbe24..4860340b756c 100644 --- 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 @@ -32,7 +32,6 @@ import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Supplier; import jdk.graal.compiler.core.common.LibGraalSupport; @@ -152,14 +151,8 @@ private static long getJNIEnv() { @Platforms(Platform.HOSTED_ONLY.class) @Override - public Map getModuleMap() { - return libGraalLoader.getModuleMap(); - } - - @Platforms(Platform.HOSTED_ONLY.class) - @Override - public Set getServicesModules() { - return libGraalLoader.getServicesModules(); + public Map getClassModuleMap() { + return libGraalLoader.getClassModuleMap(); } @Override 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 index 7828b2f99260..bad24a8cfb7b 100644 --- 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 @@ -34,7 +34,6 @@ import java.lang.ref.ReferenceQueue; import java.util.Map; import java.util.ServiceLoader; -import java.util.Set; import java.util.function.Supplier; /** @@ -81,19 +80,14 @@ public interface LibGraalSupport { @Platforms(Platform.HOSTED_ONLY.class) Supplier createGlobal(long initialValue); - /** - * Gets the names of the modules containing classes that can be annotated by - * {@code LibGraalService}. - */ - Set getServicesModules(); - /** * 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 compiled into libgraal. + * enclosing module. There is one entry in the map for each class loadable via the libgraal + * class loader. * * @return an unmodifiable map */ - Map getModuleMap(); + Map getClassModuleMap(); /** * Notifies the runtime that the caller is at a point where the live set of objects is expected 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 b78cfb2f7d35..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 @@ -38,7 +38,6 @@ import java.util.Properties; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; -import java.util.Set; import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.core.common.LibGraalSupport; @@ -115,12 +114,8 @@ private static void addProviders(String arch, Class service) { LibGraalSupport libgraal = LibGraalSupport.INSTANCE; if (libgraal != null) { libgraalServices = new HashMap<>(); - Set libgraalServicesModules = libgraal.getServicesModules(); - Map modules = libgraal.getModuleMap(); String arch = getJVMCIArch(); - modules.entrySet().stream()// - .filter(e -> libgraalServicesModules.contains(e.getValue()))// - .map(Map.Entry::getKey)// + libgraal.getClassModuleMap().keySet().stream()// .map(GraalServices::loadClassOrNull)// .filter(c -> c != null && c.getAnnotation(LibGraalService.class) != null)// .forEach(service -> addProviders(arch, service)); diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java index 048d54c97be2..6d1a165c6dd8 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java +++ b/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java @@ -40,9 +40,7 @@ */ package jdk.graal.nativeimage; -import java.nio.file.Path; import java.util.Map; -import java.util.Set; /** * The class loader used to load the Graal and JVMCI classes compiled into libgraal implements this @@ -52,18 +50,6 @@ */ public interface LibGraalLoader { - /** - * Gets the {@code java.home} of the JDK whose runtime image contains the Graal and JVMCI - * classes from which libgraal will be built. - */ - Path getJavaHome(); - - /** - * Gets the ClassLoader that should be seen at image runtime if a class was loaded at image - * build-time by this loader. - */ - ClassLoader getRuntimeClassLoader(); - /** * 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 @@ -71,11 +57,5 @@ public interface LibGraalLoader { * * @return an unmodifiable map */ - Map getModuleMap(); - - /** - * Gets the names of the modules containing classes that can be annotated by - * {@code LibGraalService}. - */ - Set getServicesModules(); + Map getClassModuleMap(); } 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 36202851abff..27d38e45d569 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 @@ -125,15 +125,6 @@ public void duringSetup(DuringSetupAccess access) { if (libGraalLoader != null) { 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/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index c47649e215f5..f41858327822 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 @@ -274,7 +274,7 @@ public void loadAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoa LibGraalLoader loader = getLibGraalLoader(); if (loader != null) { /* If we have a LibGraalLoader, register its classes to the image builder */ - for (String fqn : loader.getModuleMap().keySet()) { + for (String fqn : loader.getClassModuleMap().keySet()) { try { var clazz = ((ClassLoader) loader).loadClass(fqn); imageClassLoader.handleClass(clazz); From 8ac8e3087753301bc3b10cad2b2eebb5cf86e479 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 12 Feb 2025 15:55:02 +0100 Subject: [PATCH 6/9] rename jdk.graal.nativeimage to org.graalvm.nativeimage.libgraal --- compiler/CHANGELOG.md | 2 +- compiler/mx.compiler/suite.py | 8 ++--- .../loader/HostedLibGraalClassLoader.java | 15 +++++----- .../libgraal/LibGraalClassLoader.java | 2 +- .../compiler/libgraal/LibGraalFeature.java | 30 +++++++++---------- .../libgraal/LibGraalSupportImpl.java | 24 +++++++-------- .../truffle/LibGraalTruffleEntryPoints.java | 2 +- .../compiler/core/common/LibGraalSupport.java | 2 +- sdk/mx.sdk/mx_sdk.py | 2 +- sdk/mx.sdk/suite.py | 14 ++++----- .../snapshot.sigtest | 6 ++-- .../nativeimage/libgraal}/LibGraalLoader.java | 2 +- .../libgraal}/LibGraalRuntime.java | 4 +-- .../libgraal}/hosted/GlobalData.java | 4 +-- .../libgraal/hosted}/package-info.java | 5 ++-- .../libgraal}/impl/GlobalDataSupport.java | 6 ++-- .../impl/LibGraalRuntimeSupport.java | 6 ++-- .../nativeimage/libgraal}/package-info.java | 5 ++-- substratevm/mx.substratevm/suite.py | 6 ++-- .../oracle/svm/core/c/GlobalLongSupplier.java | 2 +- .../libgraal/LibGraalRuntimeSupportImpl.java | 2 +- .../graal/hosted/GraalCompilerFeature.java | 2 +- .../oracle/svm/hosted/ClassLoaderFeature.java | 2 +- .../svm/hosted/GlobalDataSupportImpl.java | 2 +- .../hosted/NativeImageClassLoaderSupport.java | 2 +- .../hosted/NativeImageGeneratorRunner.java | 1 - .../ClassInitializationFeature.java | 2 +- .../ClassInitializationSupport.java | 2 +- .../hosted/doc-files/LibGraalClassLoader.txt | 2 +- .../com/oracle/svm/util/ModuleSupport.java | 2 +- 30 files changed, 84 insertions(+), 82 deletions(-) rename sdk/src/{jdk.graal.nativeimage => org.graalvm.nativeimage.libgraal}/snapshot.sigtest (83%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/LibGraalLoader.java (98%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/LibGraalRuntime.java (97%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/hosted/GlobalData.java (96%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted}/package-info.java (92%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/impl/GlobalDataSupport.java (92%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/impl/LibGraalRuntimeSupport.java (93%) rename sdk/src/{jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted => org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal}/package-info.java (92%) diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index fd6f78b4a83e..545af0571eff 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -3,7 +3,7 @@ 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 `jdk.graal.nativeimage` SDK module. With this module, all logic for building +* (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 diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index edcd40e3a381..9a6d793c496a 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -484,7 +484,7 @@ "javaCompliance" : "21+", "dependencies" : [ "GRAAL", - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", "sdk:JNIUTILS", "sdk:NATIVEBRIDGE" ], @@ -512,7 +512,7 @@ "workingSets" : "Graal", "javaCompliance" : "21+", "dependencies" : [ - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", ], "requiresConcealed" : { "java.base" : [ @@ -676,7 +676,7 @@ "jdk.graal.compiler.libgraal.loader" ], "distDependencies" : [ - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", "GRAAL", ], "maven": False, @@ -694,7 +694,7 @@ ], "distDependencies": [ "GRAAL", - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", "sdk:JNIUTILS", "sdk:NATIVEIMAGE", "sdk:NATIVEBRIDGE" diff --git a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java index 2cc09d6b2038..2064a0fddede 100644 --- a/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java +++ b/compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/libgraal/loader/HostedLibGraalClassLoader.java @@ -24,13 +24,6 @@ */ package jdk.graal.compiler.libgraal.loader; -import jdk.graal.nativeimage.LibGraalLoader; -import jdk.internal.jimage.BasicImageReader; -import jdk.internal.module.ModulePath; -import jdk.internal.module.Modules; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -59,6 +52,14 @@ import java.util.Set; import java.util.stream.Stream; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; + +import jdk.internal.jimage.BasicImageReader; +import jdk.internal.module.ModulePath; +import jdk.internal.module.Modules; + /** * 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 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 index f47fe441b156..d8ad32e8bdb4 100644 --- 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 @@ -28,7 +28,7 @@ /** * The image runtime class loader that {@linkplain DuringSetupAccess#registerObjectReplacer - * replaces} the build-time instance of the {@link jdk.graal.nativeimage.LibGraalLoader}. + * replaces} the build-time instance of the {@link org.graalvm.nativeimage.libgraal.LibGraalLoader}. */ final class LibGraalClassLoader extends ClassLoader { 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 index f0718f7fc4a7..5484eb3b7b76 100644 --- 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 @@ -41,20 +41,6 @@ import java.util.function.BooleanSupplier; import java.util.function.Consumer; -import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -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.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.services.JVMCIServiceLocator; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.NativeBridgeSupport; import org.graalvm.nativeimage.ImageSingletons; @@ -64,14 +50,28 @@ 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.nativeimage.LibGraalLoader; +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). 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 index 4860340b756c..ff533e212736 100644 --- 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 @@ -34,18 +34,6 @@ import java.util.Map; import java.util.function.Supplier; -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.graal.nativeimage.LibGraalLoader; -import jdk.graal.nativeimage.LibGraalRuntime; -import jdk.graal.nativeimage.hosted.GlobalData; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; - import jdk.graal.compiler.options.OptionValues; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; @@ -60,6 +48,18 @@ 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 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 index dcc3b7d1a96a..50612c3fd3c8 100644 --- 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 @@ -61,7 +61,7 @@ import jdk.graal.compiler.truffle.TruffleCompilerOptions; import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilationSupport; import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; -import jdk.graal.nativeimage.LibGraalRuntime; +import org.graalvm.nativeimage.libgraal.LibGraalRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.meta.ResolvedJavaMethod; 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 index bad24a8cfb7b..aaad01793cd1 100644 --- 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 @@ -38,7 +38,7 @@ /** * Service provider interface (SPI) defining support needed by libgraal. Using an SPI instead of - * directly depending on modules such as {@code jdk.graal.nativeimage} and + * 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. diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 090205802b86..d7674d55a569 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -158,7 +158,7 @@ def upx(args): third_party_license_files=[], dependencies=['sdkc'], jar_distributions=[], - boot_jars=['sdk:NATIVEIMAGE', 'sdk:GRAAL_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 44627956b91c..ac5744c25674 100644 --- a/sdk/mx.sdk/suite.py +++ b/sdk/mx.sdk/suite.py @@ -438,7 +438,7 @@ }, # Native Image API extensions for libgraal. - "jdk.graal.nativeimage" : { + "org.graalvm.nativeimage.libgraal" : { "subDir" : "src", "sourceDirs" : ["src"], "dependencies" : [ @@ -841,22 +841,22 @@ class UniversalDetector { }, }, - "GRAAL_NATIVEIMAGE" : { + "NATIVEIMAGE_LIBGRAAL" : { "subDir" : "src", "dependencies" : [ - "jdk.graal.nativeimage", + "org.graalvm.nativeimage.libgraal", ], "distDependencies" : ["NATIVEIMAGE"], "javadocType": "api", "moduleInfo" : { - "name" : "jdk.graal.nativeimage", + "name" : "org.graalvm.nativeimage.libgraal", "requires" : [ "transitive org.graalvm.nativeimage", ], "exports" : [ - "jdk.graal.nativeimage", - "jdk.graal.nativeimage.hosted", - "jdk.graal.nativeimage.impl to org.graalvm.nativeimage.builder", + "org.graalvm.nativeimage.libgraal", + "org.graalvm.nativeimage.libgraal.hosted", + "org.graalvm.nativeimage.libgraal.impl to org.graalvm.nativeimage.builder", ], "uses" : [], "opens" : [], diff --git a/sdk/src/jdk.graal.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest similarity index 83% rename from sdk/src/jdk.graal.nativeimage/snapshot.sigtest rename to sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest index 98f6e42a9942..dc9525b4f04c 100644 --- a/sdk/src/jdk.graal.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage.libgraal/snapshot.sigtest @@ -1,17 +1,17 @@ #Signature file v4.1 #Version -CLSS public abstract interface jdk.graal.nativeimage.LibGraalLoader +CLSS public abstract interface org.graalvm.nativeimage.libgraal.LibGraalLoader meth public abstract java.util.Map getClassModuleMap() -CLSS public final jdk.graal.nativeimage.LibGraalRuntime +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 jdk.graal.nativeimage.hosted.GlobalData +CLSS public final org.graalvm.nativeimage.libgraal.hosted.GlobalData meth public static java.util.function.Supplier createGlobal(long) supr java.lang.Object diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java similarity index 98% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java index 6d1a165c6dd8..f82b1f09cc86 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalLoader.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalLoader.java @@ -38,7 +38,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package jdk.graal.nativeimage; +package org.graalvm.nativeimage.libgraal; import java.util.Map; diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java similarity index 97% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java index ea2c782ce5b6..352a847be6cd 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/LibGraalRuntime.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/LibGraalRuntime.java @@ -38,14 +38,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package jdk.graal.nativeimage; +package org.graalvm.nativeimage.libgraal; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import org.graalvm.nativeimage.ImageSingletons; -import jdk.graal.nativeimage.impl.LibGraalRuntimeSupport; +import org.graalvm.nativeimage.libgraal.impl.LibGraalRuntimeSupport; /** * LibGraal specific extensions to {@link org.graalvm.nativeimage}. diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java similarity index 96% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java index 40fdba2f13f7..18a2209f7a29 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/GlobalData.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/GlobalData.java @@ -38,9 +38,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package jdk.graal.nativeimage.hosted; +package org.graalvm.nativeimage.libgraal.hosted; -import jdk.graal.nativeimage.impl.GlobalDataSupport; +import org.graalvm.nativeimage.libgraal.impl.GlobalDataSupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java similarity index 92% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java index 33dc85dd0427..15f3045a73ae 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/package-info.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/hosted/package-info.java @@ -44,8 +44,9 @@ ) */ /** - * Extensions to the GraalVM SDK Native Image API to customize building libgraal. + * 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 jdk.graal.nativeimage; +package org.graalvm.nativeimage.libgraal.hosted; diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java similarity index 92% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java index a78bad798e08..03b8a67033e8 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/GlobalDataSupport.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/GlobalDataSupport.java @@ -38,14 +38,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package jdk.graal.nativeimage.impl; +package org.graalvm.nativeimage.libgraal.impl; -import jdk.graal.nativeimage.hosted.GlobalData; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; import java.util.function.Supplier; /** - * Service provider interface for implementation of {@link GlobalData}. + * Interface for Native Image to implement {@link GlobalData}. */ public interface GlobalDataSupport { diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java similarity index 93% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java index bfd3639bd43a..28910ffaf78f 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/impl/LibGraalRuntimeSupport.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/impl/LibGraalRuntimeSupport.java @@ -38,12 +38,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package jdk.graal.nativeimage.impl; +package org.graalvm.nativeimage.libgraal.impl; -import jdk.graal.nativeimage.LibGraalRuntime; +import org.graalvm.nativeimage.libgraal.LibGraalRuntime; /** - * Service provider interface for implementation of {@link LibGraalRuntime}. + * Interface for Native Image to implement {@link LibGraalRuntime}. */ public interface LibGraalRuntimeSupport { diff --git a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java similarity index 92% rename from sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java rename to sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java index 2c6bd106abcc..77758b1c5e0b 100644 --- a/sdk/src/jdk.graal.nativeimage/src/jdk/graal/nativeimage/hosted/package-info.java +++ b/sdk/src/org.graalvm.nativeimage.libgraal/src/org/graalvm/nativeimage/libgraal/package-info.java @@ -44,8 +44,9 @@ ) */ /** - * Extensions to the GraalVM SDK Native Image API to customize building libgraal. + * 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 jdk.graal.nativeimage.hosted; +package org.graalvm.nativeimage.libgraal; diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 93b04a09bc59..a9ce2286a9c9 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -219,7 +219,7 @@ "sourceDirs": ["src"], "dependencies": [ "sdk:NATIVEIMAGE", - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", "compiler:GRAAL", ], "requiresConcealed" : { @@ -1714,7 +1714,7 @@ "transitive org.graalvm.nativeimage.pointsto", "org.graalvm.collections", "org.graalvm.truffle.compiler", - "jdk.graal.nativeimage" + "org.graalvm.nativeimage.libgraal" ], "uses" : [ "org.graalvm.nativeimage.Platform", @@ -2144,7 +2144,7 @@ "distDependencies": [ "compiler:GRAAL", "sdk:NATIVEIMAGE", - "sdk:GRAAL_NATIVEIMAGE", + "sdk:NATIVEIMAGE_LIBGRAAL", ], "exclude": [ ], 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 index 9bd5c8922e8e..8e105e0c7e6a 100644 --- 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 @@ -25,7 +25,7 @@ package com.oracle.svm.core.c; import jdk.graal.compiler.word.Word; -import jdk.graal.nativeimage.hosted.GlobalData; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; import org.graalvm.word.PointerBase; import java.util.function.Supplier; 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 index be2c1dc81a26..40a819593aae 100644 --- 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 @@ -31,7 +31,7 @@ import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.util.VMError; -import jdk.graal.nativeimage.impl.LibGraalRuntimeSupport; +import org.graalvm.nativeimage.libgraal.impl.LibGraalRuntimeSupport; @AutomaticallyRegisteredImageSingleton({LibGraalRuntimeSupport.class}) public final class LibGraalRuntimeSupportImpl implements LibGraalRuntimeSupport { 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 fe1f21163b99..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 @@ -30,7 +30,7 @@ import com.oracle.svm.util.ReflectionUtil; import jdk.graal.compiler.serviceprovider.GlobalAtomicLong; -import jdk.graal.nativeimage.hosted.GlobalData; +import org.graalvm.nativeimage.libgraal.hosted.GlobalData; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.FieldValueTransformer; 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 27d38e45d569..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.nativeimage.LibGraalLoader; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import jdk.internal.loader.ClassLoaders; import jdk.vm.ci.meta.JavaConstant; 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 index 51659fa7b383..8a8d427789c0 100644 --- 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 @@ -29,7 +29,7 @@ import com.oracle.svm.core.c.GlobalLongSupplier; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import jdk.graal.nativeimage.impl.GlobalDataSupport; +import org.graalvm.nativeimage.libgraal.impl.GlobalDataSupport; @AutomaticallyRegisteredImageSingleton(GlobalDataSupport.class) public final class GlobalDataSupportImpl implements GlobalDataSupport { 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 f41858327822..b82dcea5de2c 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 @@ -77,7 +77,7 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.util.ModuleSupport; -import jdk.graal.nativeimage.LibGraalLoader; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 0e9d89b72406..3f775ec9680a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -239,7 +239,6 @@ private static void transitiveRequires(boolean verbose, Module requiringModule, /* graal */ potentialNeedModule.getName().startsWith("org.graalvm.") || potentialNeedModule.getName().startsWith("jdk.graal.compiler") || - potentialNeedModule.getName().startsWith("jdk.graal.nativeimage") || /* enterprise graal */ potentialNeedModule.getName().startsWith("com.oracle.graal.") || /* exclude all truffle modules */ 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 e418fce47499..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,7 +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("jdk.graal.nativeimage", 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 2dc212f2e769..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 @@ -45,7 +45,7 @@ import java.util.stream.Collectors; import jdk.graal.compiler.core.common.ContextClassLoaderScope; -import jdk.graal.nativeimage.LibGraalLoader; +import org.graalvm.nativeimage.libgraal.LibGraalLoader; import org.graalvm.collections.EconomicSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; 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 index 040c6fbfa7c5..17c5d6ad420b 100644 --- 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 @@ -1,4 +1,4 @@ -Specify the fully qualified name of a class that implements jdk.graal.nativeimage.LibGraalLoader. +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. 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 d9c3694b9328..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 @@ -52,7 +52,7 @@ public final class ModuleSupport { "com.oracle.graal.graal_enterprise", "com.oracle.svm.svm_enterprise", "jdk.graal.compiler", - "jdk.graal.nativeimage", + "org.graalvm.nativeimage.libgraal", "jdk.internal.vm.ci", "org.graalvm.nativeimage", "org.graalvm.nativeimage.base", From 478498686324c90e4ae8aa06bcd4cbdb3c897d1c Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 12 Feb 2025 15:16:57 +0100 Subject: [PATCH 7/9] only set libgraal related image system properties when building libgraal --- .../compiler/core/common/LibGraalSupport.java | 15 ++++----------- .../hotspot/CompilerConfigurationFactory.java | 6 +++--- .../genscavenge/graal/GenScavengeGCFeature.java | 7 +++---- .../src/com/oracle/svm/core/SubstrateOptions.java | 3 +++ .../svm/core}/doc-files/LibGraalClassLoader.txt | 0 .../svm/core/jdk/SystemPropertiesSupport.java | 15 +++++++++++++++ .../svm/hosted/NativeImageClassLoaderSupport.java | 4 ++-- .../com/oracle/svm/hosted/NativeImageOptions.java | 3 --- 8 files changed, 30 insertions(+), 23 deletions(-) rename substratevm/src/{com.oracle.svm.hosted/src/com/oracle/svm/hosted => com.oracle.svm.core/src/com/oracle/svm/core}/doc-files/LibGraalClassLoader.txt (100%) 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 index aaad01793cd1..cad55e0c22a3 100644 --- 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 @@ -27,7 +27,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.RuntimeSystemProperties; import java.io.PrintStream; import java.lang.ref.Reference; @@ -46,17 +45,11 @@ public interface LibGraalSupport { /** - * Prefix to be used when {@linkplain RuntimeSystemProperties#register registering} properties - * describing the image configuration for libgraal. This is analogous to the configuration info - * displayed by {@code -XshowSettings}. - *

    - * For example: - * - *

    -     * RuntimeSystemProperties.register(NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", "serial");
    -     * 
    + * 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 NATIVE_IMAGE_SETTING_KEY_PREFIX = "org.graalvm.nativeimage.setting."; + String LIBGRAAL_SETTING_PROPERTY_PREFIX = "libgraal.setting."; /** * Called to signal a fatal, non-recoverable error. This method does not return or throw an 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 1ef39a477e73..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,7 +25,7 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static jdk.graal.compiler.core.common.LibGraalSupport.NATIVE_IMAGE_SETTING_KEY_PREFIX; +import static jdk.graal.compiler.core.common.LibGraalSupport.LIBGRAAL_SETTING_PROPERTY_PREFIX; import java.util.ArrayList; import java.util.Collections; @@ -279,9 +279,9 @@ private Object getLoadedFromLocation(boolean verbose) { 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(NATIVE_IMAGE_SETTING_KEY_PREFIX))// + .filter(e -> e.getKey().toString().startsWith(LIBGRAAL_SETTING_PROPERTY_PREFIX))// .map(e -> { - String key = e.getKey().toString().substring(NATIVE_IMAGE_SETTING_KEY_PREFIX.length()); + String key = e.getKey().toString().substring(LIBGRAAL_SETTING_PROPERTY_PREFIX.length()); String val = e.getValue().toString(); return val.isEmpty() ? key : key + "=" + val; })// 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 e38bd4a27ce7..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,7 +28,7 @@ import java.util.List; import java.util.Map; -import jdk.graal.compiler.core.common.LibGraalSupport; +import com.oracle.svm.core.jdk.SystemPropertiesSupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -69,7 +69,6 @@ import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.util.Providers; -import org.graalvm.nativeimage.hosted.RuntimeSystemProperties; @AutomaticallyRegisteredFeature class GenScavengeGCFeature implements InternalFeature { @@ -131,8 +130,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { ImageSingletons.add(CommittedMemoryProvider.class, createCommittedMemoryProvider()); } - String gcName = Heap.getHeap().getGC().getName(); - RuntimeSystemProperties.register(LibGraalSupport.NATIVE_IMAGE_SETTING_KEY_PREFIX + "gc", gcName); + // 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/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.hosted/src/com/oracle/svm/hosted/doc-files/LibGraalClassLoader.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/LibGraalClassLoader.txt similarity index 100% rename from substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/doc-files/LibGraalClassLoader.txt rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/LibGraalClassLoader.txt 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.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index b82dcea5de2c..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 @@ -572,9 +572,9 @@ private Stream processOption(OptionKey loaderClass = Class.forName(className, true, classLoader); if (!LibGraalLoader.class.isAssignableFrom(loaderClass)) { 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<>(""); } From 9a744b5933b865b0c801bf6403f1a70b93be738e Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 12 Feb 2025 16:49:31 +0100 Subject: [PATCH 8/9] added OWNERS.toml for org.graalvm.nativeimage and org.graalvm.nativeimage.libgraal --- sdk/src/org.graalvm.nativeimage.libgraal/OWNERS.toml | 11 +++++++++++ sdk/src/org.graalvm.nativeimage/OWNERS.toml | 9 +++++++++ 2 files changed, 20 insertions(+) create mode 100644 sdk/src/org.graalvm.nativeimage.libgraal/OWNERS.toml create mode 100644 sdk/src/org.graalvm.nativeimage/OWNERS.toml 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/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" +] From 7d5592ae1deb7dcbe83f04aa4165823d152e9413 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 13 Feb 2025 11:21:44 +0100 Subject: [PATCH 9/9] removed IsolateSupport.getIsolateID --- .../compiler/core/common/LibGraalSupport.java | 2 -- .../graal/compiler/debug/GlobalMetrics.java | 4 +-- .../compiler/serviceprovider/IsolateUtil.java | 9 +++--- .../nativeimage/libgraal/LibGraalRuntime.java | 2 -- .../nativeimage/impl/IsolateSupport.java | 10 +----- .../src/com/oracle/svm/core/Isolates.java | 4 +++ .../core/c/function/IsolateSupportImpl.java | 32 ------------------- .../jni/functions/JNIInvocationInterface.java | 9 +++--- .../libgraal/LibGraalRuntimeSupportImpl.java | 5 ++- .../substitutions/GraalSubstitutions.java | 4 +-- 10 files changed, 20 insertions(+), 61 deletions(-) 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 index cad55e0c22a3..11f37c45c5da 100644 --- 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 @@ -108,8 +108,6 @@ public interface LibGraalSupport { /** * 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/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/serviceprovider/IsolateUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/IsolateUtil.java index 2e8218f2f547..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 @@ -43,9 +43,9 @@ public static long getIsolateAddress() { } /** - * 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() { LibGraalSupport libgraal = LibGraalSupport.INSTANCE; @@ -58,7 +58,8 @@ public static long getIsolateID() { /** * 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/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 index 352a847be6cd..a2a051e08170 100644 --- 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 @@ -79,8 +79,6 @@ public static void notifyLowMemoryPoint(boolean 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. - * - * @return a non-zero value */ public static long getIsolateID() { return ImageSingletons.lookup(LibGraalRuntimeSupport.class).getIsolateID(); 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/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/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/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 index 40a819593aae..67c1cddf93fd 100644 --- 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 @@ -24,8 +24,7 @@ */ package com.oracle.svm.core.libgraal; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.IsolateSupport; +import com.oracle.svm.core.Isolates; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.heap.Heap; @@ -48,7 +47,7 @@ public void notifyLowMemoryPoint(boolean suggestFullGC) { @Override public long getIsolateID() { - return ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); + return Isolates.getIsolateId(); } @Override 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 16a1af639e9c..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 @@ -33,6 +33,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import com.oracle.svm.core.Isolates; import jdk.graal.compiler.graph.Edges; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; @@ -40,7 +41,6 @@ import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.FieldValueTransformer; -import org.graalvm.nativeimage.impl.IsolateSupport; import com.oracle.svm.core.SubstrateTargetDescription; import com.oracle.svm.core.annotate.Alias; @@ -218,7 +218,7 @@ public static long getIsolateAddress() { @Substitute public static long getIsolateID() { - return ImageSingletons.lookup(IsolateSupport.class).getIsolateID(); + return Isolates.getIsolateId(); } }