From 7c78e5f662c54265fd431e984c77be4ececa2942 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 5 Aug 2024 16:49:01 +0200 Subject: [PATCH 1/8] removed unused HotSpotCodeCacheListener --- compiler/mx.compiler/suite.py | 1 - .../hotspot/HotSpotCodeCacheListener.java | 42 ------------------- .../hotspot/HotSpotGraalVMEventListener.java | 12 ------ .../hotspot/guestgraal/BuildTime.java | 2 - .../hotspot/libgraal/LibGraalFeature.java | 2 - 5 files changed, 59 deletions(-) delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotCodeCacheListener.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index a6e866f51174..47d03be06418 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -557,7 +557,6 @@ "jdk.graal.compiler.debug.DebugHandlersFactory", "jdk.graal.compiler.debug.TTYStreamProvider", "jdk.graal.compiler.debug.PathUtilitiesProvider", - "jdk.graal.compiler.hotspot.HotSpotCodeCacheListener", "jdk.graal.compiler.hotspot.HotSpotBackendFactory", "jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider", "jdk.graal.compiler.nodes.graphbuilderconf.GeneratedPluginFactory", diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotCodeCacheListener.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotCodeCacheListener.java deleted file mode 100644 index ae3f9fb334a2..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotCodeCacheListener.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2015, 2018, 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; - -import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; - -public interface HotSpotCodeCacheListener { - /** - * Notifies this object on successful install into the CodeCache. - * - * @param codeCache the code cache into which the code was installed - * @param installedCode the code that was installed - * @param compiledCode the compiled code from which {@code installedCode} was produced - */ - default void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { - - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java index a75092972973..e5b1ee7f03fc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java @@ -24,13 +24,9 @@ */ package jdk.graal.compiler.hotspot; -import java.util.ArrayList; -import java.util.List; - import jdk.graal.compiler.code.CompilationResult; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugOptions; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; @@ -39,14 +35,9 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { private HotSpotGraalRuntime runtime; - private List listeners; HotSpotGraalVMEventListener(HotSpotGraalRuntime runtime) { setRuntime(runtime); - listeners = new ArrayList<>(); - for (HotSpotCodeCacheListener listener : GraalServices.load(HotSpotCodeCacheListener.class)) { - listeners.add(listener); - } } void setRuntime(HotSpotGraalRuntime runtime) { @@ -72,9 +63,6 @@ public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode inst if (debug.isLogEnabled()) { debug.log("%s", codeCache.disassemble(installedCode)); } - for (HotSpotCodeCacheListener listener : listeners) { - listener.notifyInstall(codeCache, installedCode, compiledCode); - } } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java index 156c85a2fc3f..6562c9267db6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java @@ -48,7 +48,6 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.EncodedSnippets; import jdk.graal.compiler.hotspot.HotSpotBackendFactory; -import jdk.graal.compiler.hotspot.HotSpotCodeCacheListener; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; @@ -154,7 +153,6 @@ public static void configureGraalForLibGraal(String arch, GraalServices.load(GraphBuilderInvocationPluginProvider.class); GraalServices.load(GraphDecoderInvocationPluginProvider.class); GraalServices.load(PartialEvaluatorConfiguration.class); - GraalServices.load(HotSpotCodeCacheListener.class); GraalServices.load(DisassemblerProvider.class); GraalServices.load(HotSpotInvocationPluginProvider.class); GraalServices.load(DefaultHotSpotLoweringProvider.Extensions.class); diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java index 4d0e94c1c1c2..c5748faa9c67 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java @@ -81,7 +81,6 @@ import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.hotspot.EncodedSnippets; import jdk.graal.compiler.hotspot.HotSpotBackend; -import jdk.graal.compiler.hotspot.HotSpotCodeCacheListener; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; @@ -226,7 +225,6 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { GraalServices.load(GraphBuilderInvocationPluginProvider.class); GraalServices.load(GraphDecoderInvocationPluginProvider.class); GraalServices.load(PartialEvaluatorConfiguration.class); - GraalServices.load(HotSpotCodeCacheListener.class); GraalServices.load(DisassemblerProvider.class); GraalServices.load(HotSpotInvocationPluginProvider.class); GraalServices.load(TruffleHostEnvironment.Lookup.class); From f026f58176145eb5cf30b46952a85e829d70323f Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 5 Aug 2024 22:46:53 +0200 Subject: [PATCH 2/8] use LibGraalService annotation to denote services available in libgraal --- compiler/mx.compiler/suite.py | 3 + .../processor/PluginGenerator.java | 20 +- .../compiler/code/DisassemblerProvider.java | 2 + .../compiler/core/ArchitectureSpecific.java | 3 +- .../core/common/CompilerProfiler.java | 2 + .../core/match/MatchStatementSet.java | 2 + .../compiler/debug/DebugHandlersFactory.java | 2 + .../compiler/debug/PathUtilitiesProvider.java | 3 + .../compiler/debug/TTYStreamProvider.java | 3 + .../hotspot/CompilerConfigurationFactory.java | 2 + .../hotspot/HotSpotBackendFactory.java | 2 + .../hotspot/guestgraal/BuildTime.java | 55 +++--- .../meta/DefaultHotSpotLoweringProvider.java | 2 + .../meta/HotSpotGraphBuilderPlugins.java | 2 +- .../meta/HotSpotInvocationPluginProvider.java | 2 + .../GeneratedPluginFactory.java | 3 + .../serviceprovider/GraalServices.java | 181 +++++------------- .../compiler/serviceprovider/JMXService.java | 1 + .../serviceprovider/LibGraalService.java | 39 ++++ .../PartialEvaluatorConfiguration.java | 2 + .../truffle/host/TruffleHostEnvironment.java | 2 + ...fleCallBoundaryInstrumentationFactory.java | 9 +- .../inlining/InliningPolicyProvider.java | 2 + .../GraphBuilderInvocationPluginProvider.java | 2 + .../GraphDecoderInvocationPluginProvider.java | 2 + .../hotspot/guestgraal/GuestGraalFeature.java | 7 + .../hotspot/libgraal/LibGraalFeature.java | 82 +++++--- 27 files changed, 238 insertions(+), 199 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/LibGraalService.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 47d03be06418..3f9d116eae22 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -190,11 +190,14 @@ ], }, "uses" : [ + "jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider.Extensions", "jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider", "jdk.graal.compiler.lir.LIRInstructionVerifier", "jdk.graal.compiler.core.common.CompilerProfiler", "jdk.graal.compiler.truffle.substitutions.GraphBuilderInvocationPluginProvider", "jdk.graal.compiler.truffle.phases.inlining.InliningPolicyProvider", + "jdk.graal.compiler.truffle.host.TruffleHostEnvironment.Lookup", + "jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider" ], "annotationProcessors" : [ "GRAAL_PROCESSOR" diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java index 80281ec74b1b..d4ccfcdc2560 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java @@ -110,10 +110,20 @@ private static void disambiguateNames(List plugins) { disambiguateWith(plugins, plugin -> plugin.getPluginName() + "__" + nextId[0]++); } + /** + * Map from an architecture's name as it appears in a package name to its name returned by + * {@code jdk.vm.ci.code.Architecture.getName()}. + */ + private static final Map SUPPORTED_JVMCI_ARCHITECTURES = Map.of( + "amd64", "AMD64", + "aarch64", "aarch64", + "riscv64", "riscv64"); + private static void createPluginFactory(AbstractProcessor processor, Element topLevelClass, List plugins) { PackageElement pkg = (PackageElement) topLevelClass.getEnclosingElement(); String genClassName = "PluginFactory_" + topLevelClass.getSimpleName(); + String arch = SUPPORTED_JVMCI_ARCHITECTURES.get(pkg.getSimpleName().toString()); String qualifiedGenClassName = pkg.getQualifiedName() + "." + genClassName; try { @@ -131,7 +141,15 @@ private static void createPluginFactory(AbstractProcessor processor, Element top plugin.generate(processor, out); out.printf("\n"); } - out.printf("public class %s implements GeneratedPluginFactory {\n", genClassName); + if (arch != null) { + out.printf("public class %s implements GeneratedPluginFactory, jdk.graal.compiler.core.ArchitectureSpecific {\n", genClassName); + out.printf(" @Override\n"); + out.printf(" public String getArchitecture() {\n"); + out.printf(" return \"%s\";\n", arch); + out.printf(" }\n"); + } else { + out.printf("public class %s implements GeneratedPluginFactory {\n", genClassName); + } createPluginFactoryMethod(out, plugins); out.printf("}\n"); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/DisassemblerProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/DisassemblerProvider.java index 53418b03cdf7..157327b23c1b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/DisassemblerProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/DisassemblerProvider.java @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.code; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; import jdk.graal.compiler.options.OptionValues; @@ -31,6 +32,7 @@ /** * Interface providing capability for disassembling machine code. */ +@LibGraalService public interface DisassemblerProvider { /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/ArchitectureSpecific.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/ArchitectureSpecific.java index f598858e25b5..368e891352ba 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/ArchitectureSpecific.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/ArchitectureSpecific.java @@ -30,7 +30,8 @@ public interface ArchitectureSpecific { /** * Gets the {@linkplain Architecture#getName() name} of the architecture this Graal component is - * associated with. + * associated with. Note that the JVMCI architecture names are somewhat inconsistent wrt case + * (i.e., "AMD64", "aarch64" and "riscv64"). */ String getArchitecture(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilerProfiler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilerProfiler.java index 6b1e784ab181..2986524987df 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilerProfiler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilerProfiler.java @@ -24,12 +24,14 @@ */ package jdk.graal.compiler.core.common; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.vm.ci.meta.ResolvedJavaMethod; /** * A profiling service that consumes compilation related events. The Java Flight Recorder (JFR) is * an example of such a service that can be exposed via this interface. */ +@LibGraalService public interface CompilerProfiler { /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchStatementSet.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchStatementSet.java index 156189f959bb..571f07d8d2eb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchStatementSet.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchStatementSet.java @@ -29,7 +29,9 @@ import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.core.gen.NodeLIRBuilder; import jdk.graal.compiler.core.gen.NodeMatchRules; +import jdk.graal.compiler.serviceprovider.LibGraalService; +@LibGraalService public interface MatchStatementSet extends ArchitectureSpecific { /** * @return the {@link NodeLIRBuilder} subclass which defined this set of {@link MatchStatement} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugHandlersFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugHandlersFactory.java index 7be896287c4e..2067d0a75e5c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugHandlersFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugHandlersFactory.java @@ -29,10 +29,12 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.serviceprovider.LibGraalService; /** * Factory for creating {@link DebugHandler}s. */ +@LibGraalService public interface DebugHandlersFactory { /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/PathUtilitiesProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/PathUtilitiesProvider.java index ea6693f59b67..babb66fdf814 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/PathUtilitiesProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/PathUtilitiesProvider.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.debug; +import jdk.graal.compiler.serviceprovider.LibGraalService; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -51,6 +53,7 @@ * image. Delegating to {@link StandardPathUtilitiesProvider} is the recommended way to work in the * context of building a native image. */ +@LibGraalService public interface PathUtilitiesProvider { /** * Gets a value based on {@code name} that can be passed to {@link #getPath(String, String...)} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/TTYStreamProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/TTYStreamProvider.java index 5f7513c39902..949c764060f5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/TTYStreamProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/TTYStreamProvider.java @@ -24,11 +24,14 @@ */ package jdk.graal.compiler.debug; +import jdk.graal.compiler.serviceprovider.LibGraalService; + import java.io.PrintStream; /** * Provides a {@link PrintStream} that writes to the underlying log stream of the VM. */ +@LibGraalService public interface TTYStreamProvider { PrintStream getStream(); } 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 217ec9f98595..b530a1a4879a 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 @@ -32,6 +32,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import jdk.graal.compiler.serviceprovider.LibGraalService; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.core.Instrumentation; import jdk.graal.compiler.core.common.SuppressFBWarnings; @@ -58,6 +59,7 @@ * have a unique {@link #name} and {@link #autoSelectionPriority}. The latter imposes a total * ordering between factories for the purpose of auto-selecting the factory to use. */ +@LibGraalService public abstract class CompilerConfigurationFactory implements Comparable { public enum ShowConfigurationLevel { 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 64b5caf88f06..607901b22097 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 @@ -68,6 +68,7 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.tiers.CompilerConfiguration; import jdk.graal.compiler.replacements.classfile.ClassfileBytecodeProvider; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.InitTimer; @@ -80,6 +81,7 @@ import jdk.vm.ci.meta.Value; import jdk.vm.ci.runtime.JVMCIBackend; +@LibGraalService public abstract class HotSpotBackendFactory implements ArchitectureSpecific { protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java index 6562c9267db6..361ef84cabc4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java @@ -31,6 +31,7 @@ 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; @@ -38,33 +39,25 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import jdk.graal.compiler.code.DisassemblerProvider; -import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.graal.compiler.core.ArchitectureSpecific; +import org.graalvm.collections.EconomicMap; + import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -import jdk.graal.compiler.core.match.MatchStatementSet; 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.HotSpotBackendFactory; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider; import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionsParser; import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.graal.compiler.truffle.PartialEvaluatorConfiguration; -import jdk.graal.compiler.truffle.substitutions.GraphBuilderInvocationPluginProvider; -import jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider; import jdk.graal.compiler.util.ObjectCopier; import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.services.JVMCIServiceLocator; -import org.graalvm.collections.EconomicMap; /** * This class is used at image build-time when a libgraal image gets built. Its static methods are @@ -127,37 +120,35 @@ public static long[] getSuccessorEdgesOffsets(Object 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); + } + } + /** - * This method gets called from {@code GuestGraalFeature#beforeAnalysis()}. It ensures static - * field {@code GraalServices#servicesCache} is set up correctly for Graal-usage needed in - * libgraal. It creates a new instance of EncodedSnippets exclusively from instances of - * GuestGraalClassLoader classes. The information how the EncodedSnippets object graph needs to - * look like comes from parameter encodedSnippetsData. This EncodedSnippets instance is then - * installed into static field {@code HotSpotReplacementsImpl#encodedSnippets} so that at - * libgraal run-time Graal has access to it. Finally, it passes the FoldNodePlugin Classes to - * the caller via a Consumer so that hosted GeneratedInvocationPlugin Graal class knows about - * them. + * 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, Consumer>> hostedGraalSetFoldNodePluginClasses, String encodedGuestObjects) { GraalError.guarantee(VALID_LOADER_NAME.equals(LOADER.getName()), "Only call this method from classloader " + VALID_LOADER_NAME); - GraalServices.setLibgraalConfig(new GraalServices.LibgraalConfig(LOADER, arch)); - // Services that will be used in libgraal. - GraalServices.load(CompilerConfigurationFactory.class); - GraalServices.load(HotSpotBackendFactory.class); - GraalServices.load(GraphBuilderInvocationPluginProvider.class); - GraalServices.load(GraphDecoderInvocationPluginProvider.class); - GraalServices.load(PartialEvaluatorConfiguration.class); - GraalServices.load(DisassemblerProvider.class); - GraalServices.load(HotSpotInvocationPluginProvider.class); - GraalServices.load(DefaultHotSpotLoweringProvider.Extensions.class); - GraalServices.load(CompilerProfiler.class); - GraalServices.load(MatchStatementSet.class); + Map, List> services = new HashMap<>(); + guestServiceClasses.forEach(c -> addProviders(services, arch, c)); + GraalServices.setLibgraalServices(services); try { Field cachedHotSpotJVMCIBackendFactoriesField = ObjectCopier.getField(HotSpotJVMCIRuntime.class, "cachedHotSpotJVMCIBackendFactories"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 83e9fad34653..2ba9d6d4817e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Map; +import jdk.graal.compiler.serviceprovider.LibGraalService; import org.graalvm.word.LocationIdentity; import jdk.graal.compiler.core.common.CompressEncoding; @@ -246,6 +247,7 @@ void initialize(HotSpotProviders providers, /** * Service provider interface for discovering {@link Extension}s. */ + @LibGraalService public interface Extensions { /** * Gets the extensions provided by this object. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 93b18c50ad86..1ebad0858b56 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -272,7 +272,7 @@ public void run() { }); if (!IS_IN_NATIVE_IMAGE) { - // In libgraal all NodeIntrinsics been converted into special nodes so the plugins + // In libgraal, all NodeIntrinsics have been converted into special nodes so the plugins // aren't needed. NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); invocationPlugins.defer(() -> { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPluginProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPluginProvider.java index 511a960570db..229ba91b7835 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPluginProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPluginProvider.java @@ -27,6 +27,7 @@ import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.graal.compiler.nodes.spi.Replacements; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.graal.compiler.serviceprovider.ServiceProvider; import jdk.vm.ci.code.Architecture; @@ -34,6 +35,7 @@ * Allows adding additional invocation plugins to {@link HotSpotGraphBuilderPlugins} via * {@link ServiceProvider}. */ +@LibGraalService public interface HotSpotInvocationPluginProvider { void registerInvocationPlugins(Architecture architecture, InvocationPlugins plugins, Replacements replacements); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java index d89025f9a4bd..8846ad071ed6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java @@ -24,6 +24,9 @@ */ package jdk.graal.compiler.nodes.graphbuilderconf; +import jdk.graal.compiler.serviceprovider.LibGraalService; + +@LibGraalService public interface GeneratedPluginFactory { void registerPlugins(InvocationPlugins plugins, GeneratedPluginInjectionProvider injection); 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 bf7c988cfe9e..e75813feacd0 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,18 +30,15 @@ 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.ServiceConfigurationError; import java.util.ServiceLoader; -import java.util.concurrent.atomic.AtomicReference; -import jdk.graal.compiler.core.ArchitectureSpecific; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; import jdk.internal.misc.VM; -import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.EncodedSpeculationReason; import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; import jdk.vm.ci.runtime.JVMCI; @@ -52,62 +49,37 @@ */ public final class GraalServices { - private static final Map, List> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null; + /** + * The set of services available in libgraal. This field is only non-null when + * {@link GraalServices} is loaded by the GuestGraal class loader. + */ + private static Map, List> libgraalServices; + + @ExcludeFromJacocoGeneratedReport("only called when building libgraal") + public static void setLibgraalServices(Map, List> services) { + GraalError.guarantee(IS_BUILDING_NATIVE_IMAGE, "Can only set libgraal services when building libgraal"); + GraalError.guarantee(libgraalServices == null, "Libgraal services must be set exactly once"); + GraalServices.libgraalServices = services; + } private GraalServices() { } /** - * Gets an {@link Iterable} of the providers available for {@code service}. + * Gets an {@link Iterable} of the providers available for {@code service}. When called within + * libgraal, {@code service} must be a {@link LibGraalService} annotated service type. */ @SuppressWarnings("unchecked") public static Iterable load(Class service) { - if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) { - List list = servicesCache.get(service); - if (list != null) { - return (Iterable) list; - } - if (IS_IN_NATIVE_IMAGE) { - throw new InternalError(String.format("No %s providers found when building native image", service.getName())); - } - } - - Iterable providers = load0(service); - - if (IS_BUILDING_NATIVE_IMAGE) { - synchronized (servicesCache) { - ArrayList providersList = new ArrayList<>(); - for (S provider : providers) { - if (isLibgraalProvider(provider)) { - providersList.add(provider); - } - } - providers = providersList; - servicesCache.put(service, providersList); - return providers; + if (IS_IN_NATIVE_IMAGE || libgraalServices != null) { + List list = libgraalServices.get(service); + if (list == null) { + throw new InternalError(String.format("No %s providers found in libgraal (missing %s annotation on %s?)", + service.getName(), LibGraalService.class.getName(), service.getName())); } + return (Iterable) list; } - - return providers; - } - - /** - * Determines if {@code provider} is a service provider used in libgraal. - */ - private static boolean isLibgraalProvider(Object provider) { - LibgraalConfig config = libgraalConfig(); - if (config != null) { - return config.isLibgraalProvider(provider); - } - Class c = provider.getClass(); - Module module = c.getModule(); - String name = module.getName(); - if (name != null) { - return name.equals("jdk.graal.compiler") || - name.equals("jdk.graal.compiler.management") || - name.equals("com.oracle.graal.graal_enterprise"); - } - return false; + return load0(service); } /** @@ -144,56 +116,6 @@ public static String getSavedProperty(String name) { return Services.getSavedProperty(name); } - /** - * Configuration relevant for building libgraal. - * - * @param classLoader the class loader used to load libgraal destined classes - * @param arch the {@linkplain Architecture#getName() name} of the architecture on which - * libgraal will be deployed - */ - public record LibgraalConfig(ClassLoader classLoader, String arch) { - - /** - * Determines if {@code provider} will be used in libgraal. - */ - boolean isLibgraalProvider(Object provider) { - if (provider.getClass().getClassLoader() != classLoader) { - return false; - } - if (provider instanceof ArchitectureSpecific as) { - return as.getArchitecture().equals(arch); - } - return true; - } - } - - /** - * Sentinel value for representing "default" initialization of {@link #libgraalConfig}. - */ - private static final LibgraalConfig LIBGRAAL_CONFIG_DEFAULT = new LibgraalConfig(null, null); - - private static final AtomicReference libgraalConfig = new AtomicReference<>(); - - /** - * Sets the config for building libgraal. Can only be called at most once. If called, it must be - * before any call to {@link #load(Class)}. - */ - public static void setLibgraalConfig(LibgraalConfig config) { - if (!IS_BUILDING_NATIVE_IMAGE) { - throw new InternalError("Can only set libgraal config when building libgraal"); - } - LibgraalConfig expectedValue = libgraalConfig.compareAndExchange(null, config); - if (expectedValue != null) { - throw new InternalError("Libgraal config already initialized: " + expectedValue); - } - } - - private static LibgraalConfig libgraalConfig() { - libgraalConfig.compareAndSet(null, LIBGRAAL_CONFIG_DEFAULT); - LibgraalConfig config = libgraalConfig.get(); - return config == LIBGRAAL_CONFIG_DEFAULT ? null : config; - } - private static Iterable load0(Class service) { Module module = GraalServices.class.getModule(); // Graal cannot know all the services used by another module @@ -202,37 +124,28 @@ private static Iterable load0(Class service) { module.addUses(service); } - LibgraalConfig config = libgraalConfig(); - Iterable iterable; - if (config != null && config.classLoader != null) { - iterable = ServiceLoader.load(service, config.classLoader); - } else { - iterable = ServiceLoader.load(module.getLayer(), service); - } - return new Iterable<>() { - @Override - public Iterator iterator() { - Iterator iterator = iterable.iterator(); - return new Iterator<>() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public S next() { - S provider = iterator.next(); - // Allow Graal extensions to access JVMCI - openJVMCITo(provider.getClass()); - return provider; - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } + return () -> { + ModuleLayer layer = module.getLayer(); + Iterator iterator = ServiceLoader.load(layer, service).iterator(); + return new Iterator<>() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public S next() { + S provider = iterator.next(); + // Allow Graal extensions to access JVMCI + openJVMCITo(provider.getClass()); + return provider; + } + + @Override + public void remove() { + iterator.remove(); + } + }; }; } @@ -264,7 +177,9 @@ static void openJVMCITo(Class other) { } /** - * Gets the provider for a given service for which at most one provider must be available. + * Gets the provider for {@code service} for which at most one provider must be available. When + * called within libgraal, {@code service} must be a {@link LibGraalService} annotated service + * type. * * @param service the service whose provider is being requested * @param required specifies if an {@link InternalError} should be thrown if no provider of diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/JMXService.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/JMXService.java index 58b76bbb2250..1b3539399dfc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/JMXService.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/JMXService.java @@ -31,6 +31,7 @@ * this abstraction enables avoiding a dependency to the {@code java.management} and * {@code jdk.management} modules. */ +@LibGraalService public abstract class JMXService { protected abstract long getThreadAllocatedBytes(long id); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/LibGraalService.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/LibGraalService.java new file mode 100644 index 000000000000..fb2a57819e7a --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/LibGraalService.java @@ -0,0 +1,39 @@ +/* + * 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; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a service type that is used in libgraal via a call to {@link GraalServices#load(Class)} + * or {@link GraalServices#loadSingle(Class, boolean)}}. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface LibGraalService { +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluatorConfiguration.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluatorConfiguration.java index d38d73f6983c..05b12815fe35 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluatorConfiguration.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluatorConfiguration.java @@ -24,12 +24,14 @@ */ package jdk.graal.compiler.truffle; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider; import jdk.vm.ci.code.Architecture; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.serviceprovider.GraalServices; +@LibGraalService public interface PartialEvaluatorConfiguration { /** * Name of this partial-evaluator configuration. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java index 42951a1ad830..a206b0d089c8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java @@ -26,6 +26,7 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.graal.compiler.truffle.TruffleCompilerConfiguration; import jdk.graal.compiler.truffle.TruffleCompilerImpl; @@ -151,6 +152,7 @@ public static TruffleHostEnvironment get(ResolvedJavaType relativeTo) { return lookup.lookup(relativeTo); } + @LibGraalService public interface Lookup { TruffleHostEnvironment lookup(ResolvedJavaType type); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/TruffleCallBoundaryInstrumentationFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/TruffleCallBoundaryInstrumentationFactory.java index 491b627b8a0a..4be1fc5da45c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/TruffleCallBoundaryInstrumentationFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/TruffleCallBoundaryInstrumentationFactory.java @@ -24,10 +24,12 @@ */ package jdk.graal.compiler.truffle.hotspot; +import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.meta.HotSpotRegistersProvider; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import jdk.graal.compiler.lir.asm.EntryPointDecorator; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.graal.compiler.truffle.TruffleCompilerConfiguration; import com.oracle.truffle.compiler.TruffleCompilable; @@ -48,12 +50,11 @@ * // normal compiled code * */ -public abstract class TruffleCallBoundaryInstrumentationFactory { +@LibGraalService +public abstract class TruffleCallBoundaryInstrumentationFactory implements ArchitectureSpecific { public abstract EntryPointDecorator create(TruffleCompilerConfiguration compilerConfig, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers); - /** - * Gets the architecture supported by this factory. - */ + @Override public abstract String getArchitecture(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/phases/inlining/InliningPolicyProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/phases/inlining/InliningPolicyProvider.java index 6926f6329a07..4b8a24a9db81 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/phases/inlining/InliningPolicyProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/phases/inlining/InliningPolicyProvider.java @@ -26,7 +26,9 @@ import jdk.graal.compiler.nodes.spi.CoreProviders; import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.serviceprovider.LibGraalService; +@LibGraalService public abstract class InliningPolicyProvider implements Comparable { private final int priority; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphBuilderInvocationPluginProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphBuilderInvocationPluginProvider.java index 4444303d0dc9..fc85d19502a5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphBuilderInvocationPluginProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphBuilderInvocationPluginProvider.java @@ -26,6 +26,7 @@ import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.graal.compiler.phases.util.Providers; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.graal.compiler.truffle.KnownTruffleTypes; import jdk.vm.ci.code.Architecture; @@ -38,6 +39,7 @@ *

* Implementations are responsible for checking the architecture if needed. */ +@LibGraalService public interface GraphBuilderInvocationPluginProvider { void registerInvocationPlugins(InvocationPlugins plugins, KnownTruffleTypes types, Providers providers, Architecture architecture, boolean canDelayIntrinsification); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphDecoderInvocationPluginProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphDecoderInvocationPluginProvider.java index 4d982c2ce59b..433540eaecab 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphDecoderInvocationPluginProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/GraphDecoderInvocationPluginProvider.java @@ -27,6 +27,7 @@ import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.graal.compiler.phases.util.Providers; +import jdk.graal.compiler.serviceprovider.LibGraalService; import jdk.vm.ci.code.Architecture; /** @@ -38,6 +39,7 @@ *

* Implementations are responsible for checking the architecture if needed. */ +@LibGraalService public interface GraphDecoderInvocationPluginProvider { void registerInvocationPlugins(Providers providers, Architecture architecture, String compilerConfiguration, InvocationPlugins plugins, boolean canDelayIntrinsification); diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java index f3b97865c5f4..2121ead9fbad 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java @@ -50,6 +50,7 @@ import com.oracle.svm.hosted.FeatureImpl; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; +import jdk.graal.compiler.serviceprovider.LibGraalService; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.NativeBridgeSupport; import org.graalvm.nativeimage.ImageSingletons; @@ -385,10 +386,15 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { Consumer>> hostedGraalSetFoldNodePluginClasses = GeneratedInvocationPlugin::setFoldNodePluginClasses; + List> guestServiceClasses = new ArrayList<>(); + List> serviceClasses = impl.getImageClassLoader().findAnnotatedClasses(LibGraalService.class, false); + serviceClasses.stream().map(c -> loader.loadClassOrFail(c.getName())).forEach(guestServiceClasses::add); + MethodHandle configureGraalForLibGraal = mhl.findStatic(buildTimeClass, "configureGraalForLibGraal", methodType(void.class, String.class, // arch + List.class, // guestServiceClasses Consumer.class, // registerAsInHeap Consumer.class, // hostedGraalSetFoldNodePluginClasses String.class // encodedGuestObjects @@ -401,6 +407,7 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { } configureGraalForLibGraal.invoke(arch, + guestServiceClasses, registerAsInHeap, hostedGraalSetFoldNodePluginClasses, configResult.encodedConfig()); diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java index c5748faa9c67..4651e34d9de3 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java @@ -28,16 +28,21 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.ServiceLoader; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; +import jdk.graal.compiler.hotspot.GraalHotSpotVMConfigAccess; +import jdk.graal.compiler.serviceprovider.LibGraalService; import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -73,7 +78,7 @@ import com.oracle.svm.util.ModuleSupport; import com.oracle.svm.util.ReflectionUtil; -import jdk.graal.compiler.code.DisassemblerProvider; +import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.core.GraalServiceThread; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.GraalError; @@ -86,7 +91,6 @@ import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.SnippetObjectConstant; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedPluginFactory; import jdk.graal.compiler.nodes.spi.SnippetParameterInfo; @@ -99,12 +103,7 @@ import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.serviceprovider.SpeculationReasonGroup; -import jdk.graal.compiler.truffle.PartialEvaluatorConfiguration; -import jdk.graal.compiler.truffle.host.TruffleHostEnvironment; import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; -import jdk.graal.compiler.truffle.hotspot.TruffleCallBoundaryInstrumentationFactory; -import jdk.graal.compiler.truffle.substitutions.GraphBuilderInvocationPluginProvider; -import jdk.graal.compiler.truffle.substitutions.GraphDecoderInvocationPluginProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -213,44 +212,73 @@ public void registerLowerings(RuntimeConfiguration runtimeConfig, OptionValues o hotSpotSubstrateReplacements = getReplacements(); } + /** + * Determines if {@code provider} should be added as a provider of a service. + * + * @param arch a value compatible with {@link ArchitectureSpecific#getArchitecture()} + */ + protected boolean shouldAddProvider(Object provider, String arch) { + if (provider instanceof ArchitectureSpecific as) { + if (!as.getArchitecture().equals(arch)) { + return false; + } + } else { + String name = provider.getClass().getName(); + for (var knownArch : GraalHotSpotVMConfigAccess.KNOWN_ARCHITECTURES) { + String archPackage = ".%s.".formatted(knownArch); + if (name.contains(archPackage)) { + throw VMError.shouldNotReachHere("%s should implement %s", name, ArchitectureSpecific.class); + } + } + } + Module module = provider.getClass().getModule(); + String name = module.getName(); + if (name != null) { + // Only services in the core graal modules should be added + return name.equals("jdk.graal.compiler") || + name.equals("jdk.graal.compiler.management") || + name.equals("com.oracle.graal.graal_enterprise"); + } + return false; + } + + @SuppressWarnings("unchecked") + private void addProviders(Map, List> services, String arch, Class service) { + List providers = (List) services.computeIfAbsent(service, key -> new ArrayList<>()); + ModuleLayer layer = GraalServices.class.getModule().getLayer(); + ServiceLoader.load(layer, service).stream().map(ServiceLoader.Provider::get).filter(provider -> shouldAddProvider(provider, arch)).forEach(providers::add); + } + @SuppressWarnings({"try", "unchecked"}) @Override public void beforeAnalysis(BeforeAnalysisAccess access) { FeatureImpl.BeforeAnalysisAccessImpl impl = (FeatureImpl.BeforeAnalysisAccessImpl) access; BigBang bb = impl.getBigBang(); - // Services that will not be loaded if native-image is run - // with -XX:-UseJVMCICompiler. - GraalServices.load(TruffleCallBoundaryInstrumentationFactory.class); - GraalServices.load(GraphBuilderInvocationPluginProvider.class); - GraalServices.load(GraphDecoderInvocationPluginProvider.class); - GraalServices.load(PartialEvaluatorConfiguration.class); - GraalServices.load(DisassemblerProvider.class); - GraalServices.load(HotSpotInvocationPluginProvider.class); - GraalServices.load(TruffleHostEnvironment.Lookup.class); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); + String arch = compiler.getGraalRuntime().getTarget().arch.getName(); + + ImageClassLoader imageClassLoader = impl.getImageClassLoader(); + List> serviceClasses = imageClassLoader.findAnnotatedClasses(LibGraalService.class, false); + Map, List> services = new HashMap<>(); + for (var c : serviceClasses) { + addProviders(services, arch, c); + } + GraalServices.setLibgraalServices(services); // Instantiate the truffle compiler to ensure the backends it uses are initialized. List truffleBackends = HotSpotTruffleCompilerImpl.ensureBackendsInitialized(RuntimeOptionValues.singleton()); // Filter out any cached services which are for a different architecture try { - HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); - String osArch = compiler.getGraalRuntime().getVMConfig().osArch; - String archPackage = "." + osArch + "."; - final Field servicesCacheField = ReflectionUtil.lookupField(Services.class, "servicesCache"); Map, List> servicesCache = (Map, List>) servicesCacheField.get(null); - filterArchitectureServices(archPackage, servicesCache); + filterArchitectureServices(arch, servicesCache); servicesCache.remove(GeneratedPluginFactory.class); - final Field graalServicesCacheField = ReflectionUtil.lookupField(GraalServices.class, "servicesCache"); - Map, List> graalServicesCache = (Map, List>) graalServicesCacheField.get(null); - filterArchitectureServices(archPackage, graalServicesCache); - graalServicesCache.remove(GeneratedPluginFactory.class); - Field cachedHotSpotJVMCIBackendFactoriesField = ReflectionUtil.lookupField(HotSpotJVMCIRuntime.class, "cachedHotSpotJVMCIBackendFactories"); List cachedHotSpotJVMCIBackendFactories = (List) cachedHotSpotJVMCIBackendFactoriesField.get(null); - cachedHotSpotJVMCIBackendFactories.removeIf(factory -> !factory.getArchitecture().equalsIgnoreCase(osArch)); + cachedHotSpotJVMCIBackendFactories.removeIf(factory -> !factory.getArchitecture().equalsIgnoreCase(arch)); } catch (ReflectiveOperationException ex) { throw VMError.shouldNotReachHere(ex); } From a7b636c437079511dbae4b7eabe42ad68fdbe2e0 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 8 Aug 2024 20:05:23 +0200 Subject: [PATCH 3/8] add EE GuestGraal support --- compiler/mx.compiler/mx_compiler.py | 2 +- .../core/match/MatchRuleRegistry.java | 2 +- .../hotspot/guestgraal/BuildTime.java | 28 +++++----- .../graal/compiler/options/OptionValues.java | 9 +--- .../graal/compiler/options/OptionsParser.java | 46 ++++++++++++---- .../native-image.properties | 5 +- .../guestgraal/GuestGraalClassLoader.java | 51 ++++++++++++++---- .../guestgraal/GuestGraalCompilerSupport.java | 12 ----- .../hotspot/guestgraal/GuestGraalFeature.java | 52 +++++++++++++------ .../hotspot/libgraal/LibGraalFeature.java | 42 +++++++++++---- .../ClassInitializationFeature.java | 4 +- vm/ci/ci_common/libgraal.jsonnet | 22 ++++---- 12 files changed, 181 insertions(+), 94 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index bf4652188f0c..cbfba2c4aa10 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -605,7 +605,7 @@ def compiler_gate_benchmark_runner(tasks, extraVMarguments=None, prefix='', task # ensure we can run with --enable-preview with Task(prefix + 'DaCapo_enable-preview:fop', tasks, tags=GraalTags.test, report=task_report_component) as t: if t: - _gate_dacapo('fop', 8, ['--enable-preview', '-Djdk.graal.CompilationFailureAction=ExitVM']) + _gate_dacapo('fop', 8, benchVmArgs + ['--enable-preview', '-Djdk.graal.CompilationFailureAction=ExitVM']) # run Scala DaCapo benchmarks # ############################### diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchRuleRegistry.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchRuleRegistry.java index fba07b9e2337..71e38d73a036 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchRuleRegistry.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/match/MatchRuleRegistry.java @@ -102,7 +102,7 @@ public static synchronized EconomicMap, List descriptors = EconomicMap.create(); - OptionsParser.setLibgraalOptionDescriptors(descriptors); - return descriptors; + public static Object initLibgraalOptions() { + return OptionsParser.setLibgraalOptions(OptionsParser.LibGraalOptionsInfo.create()); } /** @@ -87,23 +85,29 @@ public static Object initLibgraalOptionDescriptors() { * {@code descriptorsObject}. * * @param optionObjects a list of {@link OptionKey} objects - * @param descriptorsObject the value returned by {@link #initLibgraalOptionDescriptors()} + * @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", "unchecked"}) - public static Iterable finalizeLibgraalOptionDescriptors(List optionObjects, Object 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); - EconomicMap descriptors = (EconomicMap) descriptorsObject; + 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(); - descriptors.put(name, descriptor); + optionsInfo.descriptors().put(name, descriptor); + String module = modules.get(descriptor.getDeclaringClass().getName()); + if (module.contains("enterprise")) { + optionsInfo.enterpriseOptions().add(name); + } } } - return descriptors.getValues(); + return optionsInfo.descriptors().getValues(); } @SuppressWarnings("unused") 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 e1d08da87fa9..19a5b7efa424 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 @@ -210,7 +210,7 @@ public void printHelp(Iterable loader, PrintStream out, Strin } else { for (Map.Entry e : sortedOptions.entrySet()) { OptionDescriptor desc = e.getValue(); - if (all || !excludeOptionFromHelp(desc)) { + if (!excludeOptionFromHelp(desc)) { size++; } } @@ -229,11 +229,6 @@ public void printHelp(Iterable loader, PrintStream out, Strin } } - private static String getEdition(Class c) { - boolean eeModule = "com.oracle.graal.graal_enterprise".equals(c.getModule().getName()); - return eeModule ? "enterprise" : "community"; - } - private void printHelp(PrintStream out, String namePrefix, String key, OptionDescriptor desc) { Object value = desc.getOptionKey().getValue(this); if (value instanceof String) { @@ -243,7 +238,7 @@ private void printHelp(PrintStream out, String namePrefix, String key, OptionDes String assign = containsKey(desc.getOptionKey()) ? ":=" : "="; String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getOptionValueType().getSimpleName(); - String edition = String.format("[%s edition]", getEdition(desc.getDeclaringClass())); + String edition = String.format("[%s edition]", OptionsParser.isEnterpriseOption(desc) ? "enterprise" : "community"); String linePrefix = String.format("%s %s %s %s", name, assign, value, edition); int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length(); 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 a6d7247871e7..04e1a02b8f3b 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 @@ -30,9 +30,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Formatter; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.ServiceLoader; +import java.util.Set; import java.util.regex.Pattern; import jdk.graal.compiler.debug.GraalError; @@ -47,11 +50,25 @@ public class OptionsParser { /** - * The 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 GuestGraal class loader. + * Info about libgraal options. + * + * @param descriptors set of compiler options available in libgraal. These correspond to the + * reachable {@link OptionKey}s discovered during Native Image static analysis. This + * field is only non-null when {@link OptionsParser} is loaded by the GuestGraal + * class loader. + * @param enterpriseOptions {@linkplain OptionKey#getName() names} of enterprise options + */ + public record LibGraalOptionsInfo(EconomicMap descriptors, Set enterpriseOptions) { + public static LibGraalOptionsInfo create() { + return new LibGraalOptionsInfo(EconomicMap.create(), new HashSet<>()); + } + } + + /** + * Compiler options info available in libgraal. This field is only non-null when + * {@link OptionsParser} is loaded by the GuestGraal class loader. */ - private static EconomicMap libgraalOptionDescriptors; + private static LibGraalOptionsInfo libgraalOptions; /** * Gets an iterable of available {@link OptionDescriptors}. @@ -59,10 +76,9 @@ public class OptionsParser { @ExcludeFromJacocoGeneratedReport("contains libgraal-only path") public static Iterable getOptionsLoader() { if (IS_IN_NATIVE_IMAGE) { - GraalError.guarantee(libgraalOptionDescriptors != null, "missing options"); - return List.of(new OptionDescriptorsMap(libgraalOptionDescriptors)); + return List.of(new OptionDescriptorsMap(Objects.requireNonNull(libgraalOptions.descriptors, "missing options"))); } - boolean inGuestGraal = libgraalOptionDescriptors != null; + boolean inGuestGraal = libgraalOptions != null; if (inGuestGraal && IS_BUILDING_NATIVE_IMAGE) { /* * Graal code is being run in the context of the GuestGraal loader while building @@ -82,10 +98,11 @@ public static Iterable getOptionsLoader() { } @ExcludeFromJacocoGeneratedReport("only called when building libgraal") - public static void setLibgraalOptionDescriptors(EconomicMap descriptors) { + public static LibGraalOptionsInfo setLibgraalOptions(LibGraalOptionsInfo info) { GraalError.guarantee(IS_BUILDING_NATIVE_IMAGE, "Can only set libgraal compiler options when building libgraal"); - GraalError.guarantee(libgraalOptionDescriptors == null, "Libgraal compiler options must be set exactly once"); - OptionsParser.libgraalOptionDescriptors = descriptors; + GraalError.guarantee(libgraalOptions == null, "Libgraal compiler options must be set exactly once"); + OptionsParser.libgraalOptions = info; + return info; } /** @@ -338,4 +355,13 @@ public static boolean collectFuzzyMatches(Iterable toSearch, S } return found; } + + static boolean isEnterpriseOption(OptionDescriptor desc) { + if (IS_IN_NATIVE_IMAGE) { + return Objects.requireNonNull(libgraalOptions.enterpriseOptions, "missing options").contains(desc.getName()); + } + Class declaringClass = desc.getDeclaringClass(); + String module = declaringClass.getModule().getName(); + return module != null && module.contains("enterprise"); + } } diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties index 76901326f985..1e8dedbd08fd 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties @@ -1,5 +1,4 @@ JavaArgs = \ - -ea -esa \ --add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED \ --add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.option=ALL-UNNAMED @@ -11,6 +10,7 @@ Args = \ --enable-monitoring=heapdump \ --no-fallback \ --shared \ + --initialize-at-build-time=jdk.graal.compiler,org.graalvm.libgraal,com.oracle.truffle \ -o jvmcicompiler \ -H:+UnlockExperimentalVMOptions \ -H:+ReportExceptionStackTraces \ @@ -23,4 +23,5 @@ Args = \ -H:HeapDumpDefaultFilenamePrefix=libgraal_pid \ -H:-AllowVMInternalThreads \ -R:-AutomaticReferenceHandling \ - -H:-UseContainerSupport \ No newline at end of file + -H:-UseContainerSupport \ + -H:+AssertInitializationSpecifiedForAllClasses \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalClassLoader.java b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalClassLoader.java index 346a81dd70c4..46aed05066b4 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalClassLoader.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalClassLoader.java @@ -86,15 +86,23 @@ public class GuestGraalClassLoader extends ClassLoader { @Platforms(Platform.HOSTED_ONLY.class) // private final Map> services = new HashMap<>(); + /** + * Map from the {@linkplain Class#forName(String) name} of a class to the name of its enclosing + * module. + */ + @Platforms(Platform.HOSTED_ONLY.class) // + private final Map modules; + /** * Modules in which Graal classes and their dependencies are defined. */ - private static final Set MODULE_PREFIXES = Set.of( - "/jdk.internal.vm.ci/", - "/org.graalvm.collections/", - "/org.graalvm.word/", - "/jdk.graal.compiler/", - "/org.graalvm.truffle.compiler/"); + 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"); static { ClassLoader.registerAsParallelCapable(); @@ -106,6 +114,7 @@ public class GuestGraalClassLoader extends ClassLoader { @Platforms(Platform.HOSTED_ONLY.class) GuestGraalClassLoader(Path imagePath) { super("GuestGraalClassLoader", null); + Map modulesMap = new HashMap<>(); try { // Need access to jdk.internal.jimage ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, getClass(), false, @@ -114,8 +123,8 @@ public class GuestGraalClassLoader extends ClassLoader { for (var entry : imageReader.getEntryNames()) { int secondSlash = entry.indexOf('/', 1); if (secondSlash != -1) { - String modulePrefix = entry.substring(0, secondSlash + 1); - if (MODULE_PREFIXES.contains(modulePrefix)) { + String module = entry.substring(1, secondSlash); + if (LIBGRAAL_MODULES.contains(module)) { String resource = entry.substring(secondSlash + 1); resources.put(resource, entry); if (resource.endsWith(".class")) { @@ -124,8 +133,10 @@ public class GuestGraalClassLoader extends ClassLoader { if (resource.equals("module-info.class")) { ModuleDescriptor md = ModuleDescriptor.read(imageReader.getResourceBuffer(imageReader.findLocation(entry))); for (var p : md.provides()) { - services.computeIfAbsent(p.service(), k -> new ArrayList<>(p.providers())); + services.computeIfAbsent(p.service(), k -> new ArrayList<>()).addAll(p.providers()); } + } else { + modulesMap.put(className, module); } } } @@ -135,6 +146,15 @@ public class GuestGraalClassLoader extends ClassLoader { } catch (IOException e) { throw new RuntimeException(e); } + this.modules = Map.copyOf(modulesMap); + } + + /** + * Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the + * name of its enclosing module. + */ + public Map getModules() { + return modules; } @Override @@ -152,7 +172,18 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } @Platforms(Platform.HOSTED_ONLY.class) - Class loadClassOrFail(String name) { + public Class loadClassOrFail(Class c) { + if (c.getClassLoader() == this) { + return c; + } + if (c.isArray()) { + return loadClassOrFail(c.getComponentType()).arrayType(); + } + return loadClassOrFail(c.getName()); + } + + @Platforms(Platform.HOSTED_ONLY.class) + public Class loadClassOrFail(String name) { try { return loadClass(name); } catch (ClassNotFoundException e) { diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalCompilerSupport.java b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalCompilerSupport.java index 03f06c1a1cb0..28066bb07b2e 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalCompilerSupport.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalCompilerSupport.java @@ -24,9 +24,6 @@ */ package com.oracle.svm.graal.hotspot.guestgraal; -import java.util.HashMap; -import java.util.List; - import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -43,7 +40,6 @@ public class GuestGraalCompilerSupport { public final EconomicMap, Object> nodeClasses = ImageHeapMap.create(); public final EconomicMap, Object> instructionClasses = ImageHeapMap.create(); public final EconomicMap, Object> compositeValueClasses = ImageHeapMap.create(); - public HashMap, EconomicMap, List>> matchRuleRegistry; protected EconomicMap, Object> basePhaseStatistics = ImageHeapMap.create(); protected EconomicMap, Object> lirPhaseStatistics = ImageHeapMap.create(); @@ -54,14 +50,6 @@ static void registerStatistics(Class phaseSubClass, EconomicMap, Obj cache.put(phaseSubClass, newStatistics); } - public HashMap, EconomicMap, List>> getMatchRuleRegistry() { - return matchRuleRegistry; - } - - public void setMatchRuleRegistry(HashMap, EconomicMap, List>> matchRuleRegistry) { - this.matchRuleRegistry = matchRuleRegistry; - } - public static GuestGraalCompilerSupport get() { return ImageSingletons.lookup(GuestGraalCompilerSupport.class); } diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java index 2121ead9fbad..6bc528c9b451 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java @@ -48,6 +48,8 @@ import com.oracle.svm.graal.hotspot.GetCompilerConfig; import com.oracle.svm.graal.hotspot.GetJNIConfig; import com.oracle.svm.hosted.FeatureImpl; +import com.oracle.svm.hosted.jni.JNIFeature; +import com.oracle.svm.hosted.reflect.ReflectionFeature; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.serviceprovider.LibGraalService; @@ -85,26 +87,26 @@ *

* To build libgraal, invoke {@code native-image} with the jar containing this feature and it * dependencies. For example: - * + * *

  *      native-image -p jniutils.jar -cp guestgraal-library.jar
  * 
- * + *

* If building with mx, execute this from the {@code vm} suite: - * + * *

  *      mx --env guestgraal native-image \
  *          -p $(mx --env guestgraal --quiet path JNIUTILS) \
  *          -cp $(mx --env guestgraal --quiet path GUESTGRAAL_LIBRARY)
  * 
- * + *

* This feature is composed of these key classes: *

    *
  • {@link GuestGraalClassLoader}
  • *
  • {@link GuestGraal}
  • *
  • {@link GuestGraalSubstitutions}
  • *
- * + *

* Additionally, it defines * {@code META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties}. */ @@ -137,6 +139,16 @@ private GuestGraalFeature() { @Override public List> getRequiredFeatures() { + /* + * LibGraal needs JNIFeature for the upcalls from HotSpot and ReflectionFeature to construct + * exceptions in jdk.internal.vm.TranslatedException.create(). However, both of these + * features are automatically registered (i.e. annotated by @AutomaticallyRegisteredFeature) + * so no need to explicitly add them here. Simply trying to look them up ensures that they + * are available. + */ + ImageSingletons.lookup(ReflectionFeature.class); + ImageSingletons.lookup(JNIFeature.class); + return List.of(GuestGraalFieldsOffsetsFeature.class); } @@ -168,6 +180,10 @@ public List> getRequiredFeatures() { MethodHandle handleGlobalAtomicLongGetInitialValue; + public GuestGraalClassLoader getLoader() { + return loader; + } + /** * Performs tasks once this feature is registered. *

    @@ -263,9 +279,9 @@ private class OptionCollector implements ObjectReachableCallback { private final EconomicMap vmOptionDescriptors; /** - * Libgraal compiler options. + * Libgraal compiler options info. */ - private final Object compilerOptionDescriptors; + private final Object compilerOptionsInfo; private boolean sealed; @@ -273,8 +289,8 @@ private class OptionCollector implements ObjectReachableCallback { this.vmOptionDescriptors = vmOptionDescriptors; try { MethodType mt = methodType(Object.class); - MethodHandle mh = mhl.findStatic(buildTimeClass, "initLibgraalOptionDescriptors", mt); - compilerOptionDescriptors = mh.invoke(); + MethodHandle mh = mhl.findStatic(buildTimeClass, "initLibgraalOptions", mt); + compilerOptionsInfo = mh.invoke(); } catch (Throwable e) { throw VMError.shouldNotReachHere(e); } @@ -308,9 +324,10 @@ void afterAnalysis(AfterAnalysisAccess access) { } } try { - MethodType mt = methodType(Iterable.class, List.class, Object.class); - MethodHandle mh = mhl.findStatic(buildTimeClass, "finalizeLibgraalOptionDescriptors", mt); - Iterable values = (Iterable) mh.invoke(compilerOptions, compilerOptionDescriptors); + MethodType mt = methodType(Iterable.class, List.class, Object.class, Map.class); + MethodHandle mh = mhl.findStatic(buildTimeClass, "finalizeLibgraalOptions", mt); + Map modules = loader.getModules(); + Iterable values = (Iterable) mh.invoke(compilerOptions, compilerOptionsInfo, modules); for (Object descriptor : values) { VMError.guarantee(access.isReachable(descriptor.getClass()), "%s", descriptor.getClass()); } @@ -376,7 +393,7 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { RuntimeReflection.registerAllDeclaredClasses(Long.class); RuntimeReflection.register(ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.Long$LongCache"), "cache")); - /* Configure static state of Graal so that suitable for the GuestGraal use case */ + /* Configure static state of Graal. */ try { TargetDescription targetDescription = ImageSingletons.lookup(SubstrateTargetDescription.class); String arch = targetDescription.arch.getName(); @@ -426,7 +443,7 @@ private static void initRuntimeHandles(MethodHandle getRuntimeHandles) throws Th @SuppressWarnings("try") @Override - public void afterAnalysis(AfterAnalysisAccess a) { + public void afterAnalysis(AfterAnalysisAccess access) { /* * Verify we only have JVMCI & Graal classes reachable that are coming from * GuestGraalClassLoader except for hosted JVMCI & Graal classes that are legitimately used @@ -443,6 +460,8 @@ public void afterAnalysis(AfterAnalysisAccess a) { "GraalError"), classesPattern("jdk.graal.compiler.options", "ModifiableOptionValues", "Option.*"), + classesPattern("jdk.graal.compiler.util.json", + "JsonWriter"), classesPattern("org.graalvm.collections", "EconomicMap.*", "EmptyMap.*", "Equivalence.*", "Pair"), classesPattern("jdk.vm.ci.amd64", @@ -458,7 +477,8 @@ public void afterAnalysis(AfterAnalysisAccess a) { Set forbiddenHostedModules = Set.of("jdk.internal.vm.ci", "org.graalvm.collections", "org.graalvm.word", "jdk.graal.compiler"); - BigBang bigBang = ((AfterAnalysisAccessImpl) a).getBigBang(); + AfterAnalysisAccessImpl accessImpl = (AfterAnalysisAccessImpl) access; + BigBang bigBang = accessImpl.getBigBang(); CallTreePrinter callTreePrinter = new CallTreePrinter(bigBang); callTreePrinter.buildCallTree(); @@ -484,7 +504,7 @@ public void afterAnalysis(AfterAnalysisAccess a) { if (!forbiddenReachableTypes.isEmpty()) { VMError.shouldNotReachHere("GuestGraal build found forbidden hosted types as reachable: %s", String.join(", ", forbiddenReachableTypes)); } - optionCollector.afterAnalysis(a); + optionCollector.afterAnalysis(access); } @Override diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java index 4651e34d9de3..4646b33bffd5 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java @@ -132,7 +132,17 @@ public LibGraalFeature() { @Override public List> getRequiredFeatures() { - return List.of(JNIFeature.class, GraalCompilerFeature.class, ReflectionFeature.class); + /* + * LibGraal needs JNIFeature for the upcalls from HotSpot and ReflectionFeature to construct + * exceptions in jdk.internal.vm.TranslatedException.create(). However, both of these + * features are automatically registered (i.e. annotated by @AutomaticallyRegisteredFeature) + * so no need to explicitly add them here. Simply trying to look them up ensures that they + * are available. + */ + ImageSingletons.lookup(ReflectionFeature.class); + ImageSingletons.lookup(JNIFeature.class); + + return List.of(GraalCompilerFeature.class); } public static final class IsEnabled implements BooleanSupplier { @@ -154,8 +164,8 @@ public void duringSetup(DuringSetupAccess a) { /** * Collects all {@link OptionKey}s that are reachable at run time. *

    - * This {@linkplain OptionsParser#setLibgraalOptionDescriptors initializes} the set of compiler - * options available in libgraal to an empty set that is populated after analysis. + * This {@linkplain OptionsParser#setLibgraalOptions} initializes} the set of compiler options + * available in libgraal to an empty set that is populated after analysis. */ private static class OptionCollector implements ObjectReachableCallback> { private final ConcurrentHashMap, OptionKey> options = new ConcurrentHashMap<>(); @@ -164,19 +174,18 @@ private static class OptionCollector implements ObjectReachableCallback compilerOptionDescriptors; + private final OptionsParser.LibGraalOptionsInfo compilerOptions; /** - * Libgraal VM options. This is disjoint from {@link #compilerOptionDescriptors}. + * Libgraal VM options. This is disjoint from {@link #compilerOptions}. */ private final EconomicMap vmOptionDescriptors; private boolean sealed; OptionCollector(EconomicMap vmOptionDescriptors) { - this.compilerOptionDescriptors = EconomicMap.create(); + this.compilerOptions = OptionsParser.setLibgraalOptions(OptionsParser.LibGraalOptionsInfo.create()); this.vmOptionDescriptors = vmOptionDescriptors; - OptionsParser.setLibgraalOptionDescriptors(compilerOptionDescriptors); } @Override @@ -196,8 +205,15 @@ void afterAnalysis(AfterAnalysisAccess access) { VMError.guarantee(access.isReachable(option.getClass())); VMError.guarantee(access.isReachable(descriptor.getClass())); String name = option.getName(); - if (!isNativeImageOption(option)) { - compilerOptionDescriptors.put(name, descriptor); + if (isCompilerOption(descriptor)) { + if (option instanceof RuntimeOptionKey) { + throw VMError.shouldNotReachHere("%s cannot be a compiler option", descriptor.getLocation()); + } + compilerOptions.descriptors().put(name, descriptor); + String module = descriptor.getDeclaringClass().getModule().getName(); + if (module.contains("enterprise")) { + compilerOptions.enterpriseOptions().add(name); + } } else { vmOptionDescriptors.put(name, descriptor); } @@ -232,6 +248,10 @@ protected boolean shouldAddProvider(Object provider, String arch) { } } Module module = provider.getClass().getModule(); + return isGraalModule(module); + } + + private static boolean isGraalModule(Module module) { String name = module.getName(); if (name != null) { // Only services in the core graal modules should be added @@ -401,8 +421,8 @@ static HotSpotReplacementsImpl getReplacements() { return (HotSpotReplacementsImpl) originalProvider.getReplacements(); } - private static boolean isNativeImageOption(OptionKey key) { - return key instanceof RuntimeOptionKey; + private static boolean isCompilerOption(OptionDescriptor descriptor) { + return isGraalModule(descriptor.getDeclaringClass().getModule()); } } 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 412d471d25ce..45546f016b5b 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 @@ -183,11 +183,11 @@ private void checkImageHeapInstance(DuringAnalysisAccess access, Object obj, Obj msg += classInitializationSupport.objectInstantiationTraceMessage(obj, "2) ", culprit -> { if (culprit == null) { - return "If if it is not intended that objects of type '" + typeName + "' are persisted in the image heap, examine the stack trace and use " + + return "If it is not intended that objects of type '" + typeName + "' are persisted in the image heap, examine the stack trace and use " + SubstrateOptionsParser.commandArgument(ClassInitializationOptions.ClassInitialization, "", "initialize-at-run-time", true, true) + "to prevent instantiation of this object." + System.lineSeparator(); } else { - return "If if it is not intended that objects of type '" + typeName + "' are persisted in the image heap, examine the stack trace and use " + + return "If it is not intended that objects of type '" + typeName + "' are persisted in the image heap, examine the stack trace and use " + SubstrateOptionsParser.commandArgument(ClassInitializationOptions.ClassInitialization, culprit, "initialize-at-run-time", true, true) + "to prevent instantiation of the culprit object."; } diff --git a/vm/ci/ci_common/libgraal.jsonnet b/vm/ci/ci_common/libgraal.jsonnet index cdfc01206deb..71078d697328 100644 --- a/vm/ci/ci_common/libgraal.jsonnet +++ b/vm/ci/ci_common/libgraal.jsonnet @@ -80,6 +80,7 @@ local galahad = import '../../../ci/ci_common/galahad-common.libsonnet'; # Gate for guestgraal guestgraal_compiler:: { + local pathsep = if self.os == "windows" then ";" else ":", local guestgraal_env = std.strReplace(vm.libgraal_env, "libgraal", "guestgraal"), # LibGraal gate tasks currently expected to work local tasks = [ @@ -97,9 +98,14 @@ local galahad = import '../../../ci/ci_common/galahad-common.libsonnet'; run+: [ ['mx', '--env', guestgraal_env, 'build'], + ['set-export', 'JNIUTILS_PATH', ['mx', '--env', guestgraal_env, '--quiet', 'path', 'JNIUTILS']], + ['set-export', 'GUESTGRAAL_LIBRARY_PATH', ['mx', '--env', guestgraal_env, '--quiet', 'path', 'GUESTGRAAL_LIBRARY']], + ] + (if vm.edition == "ee" then [ + ['set-export', 'ENTERPRISE_GUESTGRAAL_LIBRARY_PATH', ['mx', '--env', guestgraal_env, '--quiet', 'path', 'ENTERPRISE_GUESTGRAAL_LIBRARY']] + ] else []) + [ ['mx', '--env', guestgraal_env, 'native-image', '-J-esa', '-J-ea', '-esa', '-ea', - '-p', ['mx', '--env', guestgraal_env, '--quiet', 'path', 'JNIUTILS'], - '-cp', ['mx', '--env', guestgraal_env, '--quiet', 'path', 'GUESTGRAAL_LIBRARY'], + '-p', '$JNIUTILS_PATH', + '-cp', '$GUESTGRAAL_LIBRARY_PATH' + pathsep + '$ENTERPRISE_GUESTGRAAL_LIBRARY_PATH', '-H:+UnlockExperimentalVMOptions', '-H:+VerifyGraalGraphs', '-H:+VerifyPhases'], ['mx', '--env', guestgraal_env, 'gate', '--task', std.join(",", tasks), '--extra-vm-argument=-XX:JVMCILibPath=$PWD/' + vm.vm_dir], ], @@ -119,11 +125,8 @@ local galahad = import '../../../ci/ci_common/galahad-common.libsonnet'; "gate-vm-libgraal_compiler-labsjdk-21-linux-amd64": {}, "gate-vm-libgraal_truffle-labsjdk-21-linux-amd64": {}, - } + if repo_config.graalvm_edition == "ce" then - { - # GuestGraal on EE is still under construction "gate-vm-guestgraal_compiler-labsjdk-latest-linux-amd64": {} - } else {}, + }, local gates = g.as_gates(gate_jobs), @@ -181,10 +184,9 @@ local galahad = import '../../../ci/ci_common/galahad-common.libsonnet'; "libgraal_compiler", "libgraal_truffle", "libgraal_compiler_quickbuild", - "libgraal_truffle_quickbuild" - ] + - # GuestGraal on EE is still under construction - (if repo_config.graalvm_edition == "ce" then ["guestgraal_compiler"] else []) + "libgraal_truffle_quickbuild", + "guestgraal_compiler" + ] ], local adjust_windows_version(gate) = ( From 6875b19d7d6f79fea8c15e59e7e1cd2e536980a1 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Sun, 11 Aug 2024 21:10:02 +0200 Subject: [PATCH 4/8] objects in libgraal must be boxed in SnippetObjectConstants --- .../graal/compiler/hotspot/EncodedSnippets.java | 4 ++-- .../HotSpotSnippetMetaAccessProvider.java | 16 +++++++++++++--- .../meta/HotSpotSnippetReflectionProvider.java | 13 +++++++++---- .../HotSpotG1WriteBarrierSnippets.java | 6 ------ .../replacements/gc/G1WriteBarrierSnippets.java | 3 --- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index 9b985fbf5cc1..491b382b1225 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -173,10 +173,10 @@ public NodeClass[] getSnippetNodeClasses() { return snippetNodeClasses; } - ResolvedJavaType lookupSnippetType(Class clazz) { + public ResolvedJavaType lookupSnippetType(Class clazz) { SnippetResolvedJavaType type = snippetTypes.get(clazz); if (type == null && isGraalClass(clazz)) { - // During libgraal image building references to Graal classes from snippets are tracked. + // During image building, references to Graal classes from snippets are tracked. // If a class isn't found in this path at runtime it means something was missed. throw new GraalError("Missing Graal class " + clazz.getName()); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index ef7c6b109a82..2f0fbc95fa30 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -29,6 +29,8 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; +import jdk.graal.compiler.debug.GraalError; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; @@ -70,10 +72,18 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { @Override public ResolvedJavaType lookupJavaType(JavaConstant constant) { - if (constant instanceof SnippetObjectConstant) { - SnippetObjectConstant objectConstant = (SnippetObjectConstant) constant; + if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - return lookupJavaType(clazz); + ResolvedJavaType type = lookupJavaType(clazz); + GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); + return type; + } + if (constant instanceof HotSpotObjectConstant hsConstant) { + Object object = hsConstant.asObject(Object.class); + if (object != null) { + Class clazz = object.getClass(); + return lookupJavaType(clazz); + } } return delegate.lookupJavaType(constant); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index 3c323232bccf..e0fdc9e8b063 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -34,6 +34,7 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.SnippetObjectConstant; import jdk.graal.compiler.word.WordTypes; @@ -46,6 +47,7 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.services.Services; public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider { @@ -61,6 +63,11 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { + if (Services.IS_IN_NATIVE_IMAGE) { + HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); + // This can only be a compiler object when in libgraal. + return new SnippetObjectConstant(object); + } return constantReflection.forObject(object); } @@ -69,12 +76,10 @@ public T asObject(Class type, JavaConstant constant) { if (constant.isNull()) { return null; } - if (constant instanceof HotSpotObjectConstant) { - HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant; + if (constant instanceof HotSpotObjectConstant hsConstant) { return hsConstant.asObject(type); } - if (constant instanceof SnippetObjectConstant) { - SnippetObjectConstant snippetObject = (SnippetObjectConstant) constant; + if (constant instanceof SnippetObjectConstant snippetObject) { return snippetObject.asObject(type); } return null; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index b99b3f81d784..0dfce37949c7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -58,7 +58,6 @@ import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaType; public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets { public static final HotSpotForeignCallDescriptor G1WBPRECALL = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NO_SIDE_EFFECT, KILLED_PRE_WRITE_BARRIER_STUB_LOCATIONS, "write_barrier_pre", @@ -176,11 +175,6 @@ protected ForeignCallDescriptor printfCallDescriptor() { return Log.LOG_PRINTF; } - @Override - protected ResolvedJavaType referenceType() { - return HotSpotReplacementsUtil.referenceType(INJECTED_METAACCESS); - } - @Override protected long referentOffset() { return HotSpotReplacementsUtil.referentOffset(INJECTED_METAACCESS); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java index db20b211de4a..80fbba4a43f4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -64,7 +64,6 @@ import jdk.graal.compiler.replacements.nodes.AssertionNode; import jdk.graal.compiler.replacements.nodes.CStringConstant; import jdk.graal.compiler.word.Word; -import jdk.vm.ci.meta.ResolvedJavaType; /** * Implementation of the write barriers for the G1 garbage collector. @@ -366,8 +365,6 @@ public void g1ArrayRangePostWriteBarrier(Address address, long length, @Constant protected abstract ForeignCallDescriptor printfCallDescriptor(); - protected abstract ResolvedJavaType referenceType(); - protected abstract long referentOffset(); protected boolean isTracingActive(int traceStartCycle) { From 8128528b8011ca4aa2764bc5e1bbc8d52306372e Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 14 Aug 2024 15:45:10 +0200 Subject: [PATCH 5/8] improved VerifyFoldableMethods to recognize implementations of PluginReplacementNode.ReplacementFunction as generated classes and deleted subsequently detected uncalled foldable methods --- .../core/test/VerifyFoldableMethods.java | 53 +++++++++++++++---- .../hotspot/GraalHotSpotVMConfig.java | 9 ---- .../hotspot/HotSpotG1BarrierSetLIRTool.java | 2 +- .../HotSpotG1WriteBarrierSnippets.java | 5 -- .../replacements/HotSpotReplacementsUtil.java | 49 +---------------- .../hotspot/stubs/ForeignCallSnippets.java | 10 ---- .../replacements/ReplacementsUtil.java | 5 -- .../gc/G1WriteBarrierSnippets.java | 2 - 8 files changed, 44 insertions(+), 91 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyFoldableMethods.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyFoldableMethods.java index 475e3c9f6380..c50e6027d2fd 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyFoldableMethods.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyFoldableMethods.java @@ -25,10 +25,12 @@ package jdk.graal.compiler.core.test; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import jdk.graal.compiler.api.replacements.Fold; +import jdk.graal.compiler.nodes.PluginReplacementNode; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; @@ -39,7 +41,9 @@ import jdk.vm.ci.meta.ResolvedJavaType; /** - * Verifies that all {@link Fold} annotated methods have at least one caller. + * Verifies that all {@link Fold} annotated methods have at least one caller from non-generated + * code. Ideally, the class should verify that foldable methods are only called from snippets but + * that requires a more global analysis (i.e., to know whether a caller is used within a snippet). */ public class VerifyFoldableMethods extends VerifyPhase { @@ -48,23 +52,47 @@ public boolean checkContract() { return false; } - private final Map foldables = new ConcurrentHashMap<>(); - ResolvedJavaType generatedInvocationPluginType; + /** + * Map from a foldable method to one of its callers. The absence of a caller is represented a + * foldable method mapping to itself. + */ + private final Map foldableCallers = new ConcurrentHashMap<>(); + + /* + * Super types or interfaces for generated classes. Calls from methods in these classes are + * ignored. + */ + Set generatedClassSupertypes; + + /** + * Determines if {@code method} is in a generated class. + */ + private boolean isGenerated(ResolvedJavaMethod method, CoreProviders context) { + if (generatedClassSupertypes == null) { + generatedClassSupertypes = Set.of( + context.getMetaAccess().lookupJavaType(GeneratedInvocationPlugin.class), + context.getMetaAccess().lookupJavaType(PluginReplacementNode.ReplacementFunction.class)); + } + ResolvedJavaType declaringClass = method.getDeclaringClass(); + for (ResolvedJavaType t : generatedClassSupertypes) { + if (t.isAssignableFrom(declaringClass)) { + return true; + } + } + return false; + } @Override protected void verify(StructuredGraph graph, CoreProviders context) { ResolvedJavaMethod method = graph.method(); if (method.getAnnotation(Fold.class) != null) { - foldables.putIfAbsent(method, false); + foldableCallers.putIfAbsent(method, method); } else { - if (generatedInvocationPluginType == null) { - generatedInvocationPluginType = context.getMetaAccess().lookupJavaType(GeneratedInvocationPlugin.class); - } - if (!generatedInvocationPluginType.isAssignableFrom(method.getDeclaringClass())) { + if (!isGenerated(method, context)) { for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { ResolvedJavaMethod callee = t.targetMethod(); if (callee.getAnnotation(Fold.class) != null) { - foldables.put(callee, true); + foldableCallers.put(callee, method); } } } @@ -72,8 +100,11 @@ protected void verify(StructuredGraph graph, CoreProviders context) { } public void finish() { - String uncalled = foldables.entrySet().stream().filter(e -> e.getValue() == false).map(e -> e.getKey().format("%H.%n(%p)")).collect(Collectors.joining(System.lineSeparator() + " ")); - if (uncalled.length() != 0) { + String uncalled = foldableCallers.entrySet().stream()// + .filter(e -> e.getValue() == e.getKey())// + .map(e -> e.getKey().format("%H.%n(%p)"))// + .collect(Collectors.joining(System.lineSeparator() + " ")); + if (!uncalled.isEmpty()) { throw new VerificationError(String.format("Methods annotated with @" + Fold.class.getSimpleName() + " appear to have no usages:%n %s", uncalled)); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 479041187184..85867f413d3d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -129,7 +129,6 @@ private HotSpotGraalRuntime.HotSpotGC getSelectedGC() throws GraalError { // of the mark word. public final int lockingMode = getFlag("LockingMode", Integer.class); - public final int lockingModeMonitor = getConstant("LockingMode::LM_MONITOR", Integer.class, 0, JDK >= 22); public final int lockingModeStack = getConstant("LockingMode::LM_LEGACY", Integer.class, 1, JDK >= 22); public final int lockingModeLightweight = getConstant("LockingMode::LM_LIGHTWEIGHT", Integer.class, 2, JDK >= 22); @@ -348,7 +347,6 @@ public int threadLastJavaFpOffset() { public final int frameInterpreterFrameLastSpOffset = getConstant("frame::interpreter_frame_last_sp_offset", Integer.class, 0, osArch.equals("amd64")); public final int lockMaskInPlace = getConstant("markWord::lock_mask_in_place", Integer.class); - public final int ageMaskInPlace = getConstant("markWord::age_mask_in_place", Integer.class); public final int unlockedMask = getConstant("markWord::unlocked_value", Integer.class); public final int monitorMask = getConstant("markWord::monitor_value", Integer.class); @@ -359,8 +357,6 @@ public int threadLastJavaFpOffset() { public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*"); public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "JavaThread*"); - public final long objectMonitorAnonymousOwner = getConstant("ObjectMonitor::ANONYMOUS_OWNER", Long.class, 1L, JDK >= 22); - public final int markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class); @@ -380,11 +376,6 @@ public long defaultPrototypeMarkWord() { public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address"); - public final int invocationCounterOffset = getFieldOffset("MethodCounters::_invocation_counter", Integer.class, "InvocationCounter"); - public final int backedgeCounterOffset = getFieldOffset("MethodCounters::_backedge_counter", Integer.class, "InvocationCounter"); - public final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class); - public final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class); - public final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization", Integer.class); public final int heapWordSize = getConstant("HeapWordSize", Integer.class); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotG1BarrierSetLIRTool.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotG1BarrierSetLIRTool.java index 51c0496073f5..d4239eae97e7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotG1BarrierSetLIRTool.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotG1BarrierSetLIRTool.java @@ -77,7 +77,7 @@ public int cardQueueIndexOffset() { @Override public byte dirtyCardValue() { - return HotSpotReplacementsUtil.dirtyCardValue(config); + return config.dirtyCardValue; } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index 0dfce37949c7..9986f7bc1f19 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -175,11 +175,6 @@ protected ForeignCallDescriptor printfCallDescriptor() { return Log.LOG_PRINTF; } - @Override - protected long referentOffset() { - return HotSpotReplacementsUtil.referentOffset(INJECTED_METAACCESS); - } - public static class Templates extends AbstractTemplates { private final SnippetInfo g1PreWriteBarrier; private final SnippetInfo g1ReferentReadBarrier; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 821617be5cc9..820250243646 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -378,26 +378,6 @@ public static int allocatePrefetchStepSize(@InjectedParameter GraalHotSpotVMConf return config.allocatePrefetchStepSize; } - @Fold - public static int invocationCounterIncrement(@InjectedParameter GraalHotSpotVMConfig config) { - return config.invocationCounterIncrement; - } - - @Fold - public static int invocationCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.invocationCounterOffset; - } - - @Fold - public static int backedgeCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.backedgeCounterOffset; - } - - @Fold - public static int invocationCounterShift(@InjectedParameter GraalHotSpotVMConfig config) { - return config.invocationCounterShift; - } - @NodeIntrinsic(value = KlassLayoutHelperNode.class) public static native int readLayoutHelper(KlassPointer object); @@ -465,11 +445,6 @@ public static void initializeObjectHeader(Word memory, Word markWord, KlassPoint StoreHubNode.write(memory, hub); } - @Fold - public static boolean useHeavyMonitors(@InjectedParameter GraalHotSpotVMConfig config) { - return config.lockingMode == config.lockingModeMonitor; - } - @Fold public static boolean useStackLocking(@InjectedParameter GraalHotSpotVMConfig config) { return config.lockingMode == config.lockingModeStack; @@ -495,11 +470,6 @@ public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConf return config.objectMonitorOwner; } - @Fold - public static long objectMonitorAnonymousOwner(@InjectedParameter GraalHotSpotVMConfig config) { - return config.objectMonitorAnonymousOwner; - } - @Fold public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.objectMonitorRecursions; @@ -530,11 +500,6 @@ public static int lockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config return config.lockMaskInPlace; } - @Fold - public static int ageMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) { - return config.ageMaskInPlace; - } - @Fold public static int metaspaceArrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.metaspaceArrayLengthOffset; @@ -837,11 +802,6 @@ static Word readInstanceKlassInitThread(KlassPointer hub) { public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags"); - @Fold - public static int klassModifierFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.klassModifierFlagsOffset; - } - public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") { @Override public ValueNode canonicalizeRead(ValueNode read, ValueNode object, ValueNode location, CoreProviders tool) { @@ -939,19 +899,12 @@ public static String referentFieldName() { return "referent"; } - @Fold public static long referentOffset(@InjectedParameter MetaAccessProvider metaAccessProvider) { return referentField(metaAccessProvider).getOffset(); } - @Fold public static ResolvedJavaField referentField(@InjectedParameter MetaAccessProvider metaAccessProvider) { - return getField(referenceType(metaAccessProvider), referentFieldName()); - } - - @Fold - public static ResolvedJavaType referenceType(@InjectedParameter MetaAccessProvider metaAccessProvider) { - return metaAccessProvider.lookupJavaType(Reference.class); + return getField(metaAccessProvider.lookupJavaType(Reference.class), referentFieldName()); } public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallSnippets.java index 0fd6ed0390fe..5593cf49e34f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallSnippets.java @@ -106,16 +106,6 @@ public static Object verifyObject(Object object) { return object; } - @Fold - static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) { - return config.verifyOopMask; - } - - @Fold - static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) { - return config.verifyOopBits; - } - /** * Gets and clears the object result from a runtime call stored in a thread local. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsUtil.java index e1997eeb0c1c..125b035a6af3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsUtil.java @@ -80,11 +80,6 @@ public static int getArrayBaseOffset(@InjectedParameter MetaAccessProvider metaA return metaAccessProvider.getArrayBaseOffset(elementKind); } - @Fold - public static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Char); - } - @Fold public static long charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { return metaAccess.getArrayIndexScale(JavaKind.Char); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java index 80fbba4a43f4..c639f3ca940c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -365,8 +365,6 @@ public void g1ArrayRangePostWriteBarrier(Address address, long length, @Constant protected abstract ForeignCallDescriptor printfCallDescriptor(); - protected abstract long referentOffset(); - protected boolean isTracingActive(int traceStartCycle) { return traceStartCycle > 0 && ((Pointer) WordFactory.pointer(gcTotalCollectionsAddress())).readInt(0) > traceStartCycle; } From 1b709d218fbea03e29d2238394dc3eda136bd672 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 15 Aug 2024 11:49:44 +0200 Subject: [PATCH 6/8] improve error message when ObjectCopier encoding fails --- .../jdk/graal/compiler/util/ObjectCopier.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/ObjectCopier.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/ObjectCopier.java index 6e12e8208a38..776891944fbb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/ObjectCopier.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/ObjectCopier.java @@ -441,7 +441,7 @@ static String[] splitSpaceSeparatedElements(String elements) { * Encodes {@code root} to a String using {@code encoder}. */ public static String encode(Encoder encoder, Object root) { - int rootId = encoder.makeId(root, ObjectPath.of("[root]")).id(); + int rootId = encoder.makeId(root, ObjectPath.of("[root:" + root.getClass().getName() + "]")).id(); GraalError.guarantee(rootId == 1, "The root object should have id of 1, not %d", rootId); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (PrintStream ps = new PrintStream(baos)) { @@ -901,12 +901,13 @@ ObjectID makeId(Object obj, ObjectPath objectPath) { checkIllegalValue(LocationIdentity.class, obj, objectPath, "must come from a static field"); checkIllegalValue(HashSet.class, obj, objectPath, "hashes are typically not stable across VM executions"); - ClassInfo classInfo = classInfos.computeIfAbsent(clazz, this::makeClassInfo); + ClassInfo classInfo = makeClassInfo(clazz, objectPath); for (Field f : classInfo.fields().values()) { - makeId(f.getType(), objectPath.add(f.getName() + ":type")); + String fieldName = f.getDeclaringClass().getSimpleName() + "#" + f.getName(); + makeId(f.getType(), objectPath.add(fieldName + ":type")); if (!f.getType().isPrimitive()) { Object fieldValue = readField(f, obj); - makeId(fieldValue, objectPath.add(f.getName())); + makeId(fieldValue, objectPath.add(fieldName)); } } } @@ -915,6 +916,14 @@ ObjectID makeId(Object obj, ObjectPath objectPath) { return objectToId.get(obj); } + private ClassInfo makeClassInfo(Class clazz, ObjectPath objectPath) { + try { + return classInfos.computeIfAbsent(clazz, this::makeClassInfo); + } catch (Throwable e) { + throw new GraalError(e, "Error creating ClassInfo%n Path: %s", objectPath); + } + } + private void encode(PrintStream out) { for (int id = 1; id < objects.size(); id++) { Object obj = objects.get(id); From 2e889d97ad911ecfcd34feb88b70d37c07d2b5ad Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 15 Aug 2024 12:17:59 +0200 Subject: [PATCH 7/8] move side-effecting code out of GuestGraalFeature constructor --- .../native-image.properties | 1 + .../hotspot/guestgraal/GuestGraalFeature.java | 28 +++++-------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties index 1e8dedbd08fd..a539ab28d1e6 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/resources/META-INF/native-image/com.oracle.svm.graal.hotspot.guestgraal/native-image.properties @@ -6,6 +6,7 @@ Args = \ -Djdk.vm.ci.services.aot=true \ -Dtruffle.TruffleRuntime= \ --add-exports=org.graalvm.nativeimage.base/com.oracle.svm.util=ALL-UNNAMED \ + --add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.feature=ALL-UNNAMED \ --features=com.oracle.svm.graal.hotspot.guestgraal.GuestGraalFeature \ --enable-monitoring=heapdump \ --no-fallback \ diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java index 6bc528c9b451..de7ea3ecedaf 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.guestgraal/src/com/oracle/svm/graal/hotspot/guestgraal/GuestGraalFeature.java @@ -48,8 +48,6 @@ import com.oracle.svm.graal.hotspot.GetCompilerConfig; import com.oracle.svm.graal.hotspot.GetJNIConfig; import com.oracle.svm.hosted.FeatureImpl; -import com.oracle.svm.hosted.jni.JNIFeature; -import com.oracle.svm.hosted.reflect.ReflectionFeature; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.serviceprovider.LibGraalService; @@ -128,27 +126,8 @@ public boolean getAsBoolean() { } } - private GuestGraalFeature() { - // GuestGraalFieldsOffsetsFeature implements InternalFeature which is in - // the non-public package com.oracle.svm.core.feature - accessModulesToClass(ModuleSupport.Access.EXPORT, GuestGraalFeature.class, "org.graalvm.nativeimage.builder"); - - // GuestGraalFeature accesses a few Graal classes (see import statements above) - accessModulesToClass(ModuleSupport.Access.EXPORT, GuestGraalFeature.class, "jdk.graal.compiler"); - } - @Override public List> getRequiredFeatures() { - /* - * LibGraal needs JNIFeature for the upcalls from HotSpot and ReflectionFeature to construct - * exceptions in jdk.internal.vm.TranslatedException.create(). However, both of these - * features are automatically registered (i.e. annotated by @AutomaticallyRegisteredFeature) - * so no need to explicitly add them here. Simply trying to look them up ensures that they - * are available. - */ - ImageSingletons.lookup(ReflectionFeature.class); - ImageSingletons.lookup(JNIFeature.class); - return List.of(GuestGraalFieldsOffsetsFeature.class); } @@ -196,6 +175,13 @@ public GuestGraalClassLoader getLoader() { */ @Override public void afterRegistration(AfterRegistrationAccess access) { + // GuestGraal uses a number of classes in org.graalvm.nativeimage.builder + accessModulesToClass(ModuleSupport.Access.EXPORT, GuestGraalFeature.class, + "org.graalvm.nativeimage.builder"); + + // GuestGraalFeature accesses a few Graal classes (see import statements above) + accessModulesToClass(ModuleSupport.Access.EXPORT, GuestGraalFeature.class, "jdk.graal.compiler"); + ImageSingletons.add(NativeBridgeSupport.class, new GuestGraalNativeBridgeSupport()); // Target_jdk_graal_compiler_serviceprovider_VMSupport.getIsolateID needs access to // org.graalvm.nativeimage.impl.IsolateSupport From c1eecddec34620215459123c4d6ca54e18bf2cd6 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 15 Aug 2024 13:59:33 +0200 Subject: [PATCH 8/8] tighten check that the type of a SnippetObjectConstant in libgraal is always a snippet type --- .../hotspot/HotSpotSnippetMetaAccessProvider.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index 2f0fbc95fa30..418ca9bf556f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -74,9 +74,12 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - ResolvedJavaType type = lookupJavaType(clazz); - GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); - return type; + if (IS_IN_NATIVE_IMAGE && HotSpotReplacementsImpl.isGraalClass(clazz)) { + ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); + GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); + return type; + } + return delegate.lookupJavaType(clazz); } if (constant instanceof HotSpotObjectConstant hsConstant) { Object object = hsConstant.asObject(Object.class);