diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index bc46e962958b..58044d22d281 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -170,7 +170,6 @@ "dependencies" : [ "sdk:WORD", "sdk:COLLECTIONS", - "sdk:NATIVEIMAGE", "truffle:TRUFFLE_COMPILER", ], "requires" : [ @@ -643,7 +642,6 @@ "distDependencies" : [ "sdk:COLLECTIONS", "sdk:WORD", - "sdk:NATIVEIMAGE", "truffle:TRUFFLE_COMPILER", ], "allowsJavadocWarnings": True, @@ -680,6 +678,7 @@ "jdk.graal.compiler.libgraal.loader" ], "distDependencies" : [ + "sdk:NATIVEIMAGE", "sdk:NATIVEIMAGE_LIBGRAAL", "GRAAL", ], @@ -699,10 +698,12 @@ "distDependencies": [ "GRAAL", "GRAAL_MANAGEMENT", + "sdk:NATIVEIMAGE", "sdk:NATIVEIMAGE_LIBGRAAL", + "sdk:COLLECTIONS", "sdk:JNIUTILS", - "sdk:NATIVEIMAGE", - "sdk:NATIVEBRIDGE" + "sdk:NATIVEBRIDGE", + "truffle:TRUFFLE_COMPILER" ], "maven": False, }, diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java index 22b23d51f133..1dbda4a08607 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java @@ -27,7 +27,10 @@ import java.io.IOException; import java.io.InputStream; import java.lang.module.ModuleDescriptor; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Path; import java.util.ArrayList; @@ -37,13 +40,18 @@ import java.util.Map; import java.util.ServiceLoader; import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; import java.util.function.Consumer; +import java.util.stream.Collectors; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.hotspot.CompilerConfig; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.NativeBridgeSupport; +import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -54,6 +62,7 @@ import org.graalvm.nativeimage.libgraal.LibGraalLoader; import jdk.graal.compiler.core.common.Fields; +import jdk.graal.compiler.core.common.LibGraalSupport.HostedOnly; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.Edges; @@ -140,6 +149,12 @@ private static Path readLibgraalJavaHome(ClassLoader cl) { @Override public void afterRegistration(AfterRegistrationAccess access) { + // Check that NativeImageSupport.inBuildtimeCode() and ImageInfo.inImageBuildtimeCode() + // agree on the system property key and value they rely on. + GraalError.guarantee(ImageInfo.PROPERTY_IMAGE_CODE_KEY.equals("org.graalvm.nativeimage.imagecode") && + ImageInfo.PROPERTY_IMAGE_CODE_VALUE_BUILDTIME.equals("buildtime"), + "%s is out of sync with %s", NativeImageSupport.class, ImageInfo.class); + ImageSingletons.add(NativeBridgeSupport.class, new LibGraalNativeBridgeSupport()); // All qualified exports to libgraal modules need to be further exported to @@ -283,12 +298,44 @@ private Map.Entry computeReplacement(Object receiver) { } } + /** + * List of reached elements annotated by {@link HostedOnly}. + */ + private final List reachedHostedOnlyElements = new ArrayList<>(); + + record HostedOnlyElementCallback(Object element, List reached) implements Consumer { + @Override + public void accept(DuringAnalysisAccess duringAnalysisAccess) { + reached.add(element); + } + } + + private void registerHostedOnlyElements(BeforeAnalysisAccess access, AnnotatedElement... elements) { + for (AnnotatedElement element : elements) { + if (element.getAnnotation(HostedOnly.class) != null) { + access.registerReachabilityHandler(new HostedOnlyElementCallback(element, reachedHostedOnlyElements), element); + } + } + } + @SuppressWarnings("unchecked") @Override public void beforeAnalysis(BeforeAnalysisAccess access) { beforeAnalysisAccess = access; new FieldOffsetsTransformer().register(access); + for (String className : libgraalLoader.getClassModuleMap().keySet()) { + try { + Class c = Class.forName(className, false, (ClassLoader) libgraalLoader); + registerHostedOnlyElements(access, c); + registerHostedOnlyElements(access, c.getDeclaredMethods()); + registerHostedOnlyElements(access, c.getDeclaredFields()); + registerHostedOnlyElements(access, c.getDeclaredConstructors()); + } catch (ClassNotFoundException e) { + throw new GraalError(e); + } + } + /* Contains static fields that depend on HotSpotJVMCIRuntime */ RuntimeClassInitialization.initializeAtRunTime(HotSpotModifiers.class); RuntimeClassInitialization.initializeAtRunTime(lookupClass("jdk.vm.ci.hotspot.HotSpotCompiledCodeStream")); @@ -379,6 +426,40 @@ private void doLegacyJVMCIInitialization() { @Override public void afterAnalysis(AfterAnalysisAccess access) { optionCollector.afterAnalysis(access); + + if (!reachedHostedOnlyElements.isEmpty()) { + Map> suggestions = new TreeMap<>(); + for (var e : reachedHostedOnlyElements) { + String name; + String value; + switch (e) { + case Method m -> { + name = "Method"; + value = m.getDeclaringClass().getName() + "." + m.getName(); + } + case Constructor c -> { + name = "Method"; + Class dc = c.getDeclaringClass(); + value = dc.getName() + "." + dc.getSimpleName(); + } + case Field f -> { + name = "Field"; + value = f.getDeclaringClass().getName() + "." + f.getName(); + } + case Class c -> { + name = "Type"; + value = c.getName(); + } + case null, default -> throw new GraalError("Unexpected element: ", e); + } + suggestions.computeIfAbsent(name, k -> new TreeSet<>()).add(value); + } + var sep = System.lineSeparator() + " "; + var s = suggestions.entrySet().stream().map(e -> e.getValue().stream().map(v -> "-H:AbortOn" + e.getKey() + "Reachable" + "=" + v).collect(Collectors.joining(sep))).collect( + Collectors.joining(sep)); + String anno = HostedOnly.class.getSimpleName(); + throw new IllegalArgumentException("@" + anno + " annotated elements reached. Add following Native Image flags to see why they are reachable:" + sep + s); + } } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java index 5c67cf2d7f15..97d9bb7f13ce 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyLibGraalContextChecks.java @@ -26,29 +26,17 @@ import java.util.List; -import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.java.LoadFieldNode; import jdk.graal.compiler.nodes.spi.CoreProviders; import jdk.graal.compiler.phases.VerifyPhase; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.services.Services; -import org.graalvm.nativeimage.ImageInfo; /** - * Ensures that the only code directly accessing - * {@link jdk.vm.ci.services.Services#IS_IN_NATIVE_IMAGE} is in - * {@link jdk.graal.compiler.serviceprovider.GraalServices}. All other code must use one of the - * following methods: - *
    - *
  • {@link GraalServices#isInLibgraal()}
  • - *
  • {@link ImageInfo#inImageCode()}
  • - *
  • {@link ImageInfo#inImageBuildtimeCode()}
  • - *
  • {@link ImageInfo#inImageRuntimeCode()}
  • - *
+ * Ensures that no code accesses {@link jdk.vm.ci.services.Services#IS_IN_NATIVE_IMAGE}. */ public class VerifyLibGraalContextChecks extends VerifyPhase { @@ -57,16 +45,6 @@ public boolean checkContract() { return false; } - static boolean isAllowedToAccess(ResolvedJavaMethod method) { - if (method.getDeclaringClass().toJavaName().equals(GraalServices.class.getName())) { - return method.getName().equals("isBuildingLibgraal") || method.getName().equals("isInLibgraal"); - } - if (method.getDeclaringClass().toJavaName().equals(HotSpotGraalCompilerFactory.class.getName())) { - return method.getName().equals("createCompiler"); - } - return false; - } - @Override protected void verify(StructuredGraph graph, CoreProviders context) { @@ -78,13 +56,11 @@ protected void verify(StructuredGraph graph, CoreProviders context) { ResolvedJavaField field = load.field(); if (field.getDeclaringClass().toJavaName().equals(Services.class.getName())) { if (field.getName().equals("IS_IN_NATIVE_IMAGE")) { - if (!isAllowedToAccess(graph.method())) { - throw new VerificationError("reading %s in %s is prohibited - use %s.isInLibgraal() instead", - field.format("%H.%n"), - graph.method().format("%H.%n(%p)"), - GraalServices.class.getName()); + throw new VerificationError("reading %s in %s is prohibited - use %s.isInLibgraal() instead", + field.format("%H.%n"), + graph.method().format("%H.%n(%p)"), + GraalServices.class.getName()); - } } } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifySystemPropertyUsage.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifySystemPropertyUsage.java index cf4efbbe9400..e3f1aa6224ca 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifySystemPropertyUsage.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifySystemPropertyUsage.java @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.core.test; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; import jdk.graal.compiler.nodes.spi.CoreProviders; @@ -89,6 +90,9 @@ protected void verify(StructuredGraph graph, CoreProviders context) { } else if (holderQualified.equals("jdk.graal.compiler.hotspot.HotSpotReplacementsImpl") && caller.getName().equals("registerSnippet")) { // We allow opening snippet registration in jargraal unit tests. return; + } else if (holderQualified.equals(NativeImageSupport.class.getName())) { + // Called as part of initializing GraalServices + return; } for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { ResolvedJavaMethod callee = t.targetMethod(); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/GraalModuleDependenciesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/GraalModuleDependenciesTest.java new file mode 100644 index 000000000000..2d4772bde537 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/GraalModuleDependenciesTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.graalvm.nativeimage.ImageInfo; +import org.junit.Test; + +import jdk.graal.compiler.core.GraalCompiler; +import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.test.SubprocessUtil; +import jdk.graal.compiler.test.SubprocessUtil.Subprocess; + +/** + * Tests that {@code jdk.graal.compiler} does not have unwanted dependencies such as + * {@code org.graalvm.nativeimage}. + */ +public class GraalModuleDependenciesTest extends GraalCompilerTest { + + static Path getJavaExe() { + Path javaHome = Path.of(System.getProperty("java.home")); + boolean isWindows = GraalServices.getSavedProperty("os.name").contains("Windows"); + Path javaExe = javaHome.resolve(Path.of("bin", isWindows ? "java.exe" : "java")); + if (!Files.isExecutable(javaExe)) { + throw new GraalError("Java launcher %s does not exist or is not executable", javaExe); + } + return javaExe; + } + + private static Subprocess run(String... command) throws InterruptedException, IOException { + Subprocess proc = SubprocessUtil.java(List.of(command)); + if (proc.exitCode != 0) { + fail("Non-zero exit code:%n%s", proc.preserveArgfile()); + } + return proc; + } + + private static String removeVersionSuffix(String moduleName) { + int at = moduleName.indexOf('@'); + if (at == -1) { + return moduleName; + } + return moduleName.substring(0, at); + } + + @Test + public void test() throws InterruptedException, IOException { + String javaExe = getJavaExe().toString(); + Subprocess proc = run(javaExe, + "--limit-modules=jdk.graal.compiler", + "--list-modules"); + + String graal = GraalCompiler.class.getModule().getName(); + String nativeImage = ImageInfo.class.getModule().getName(); + Set moduleNames = proc.output.stream().map(GraalModuleDependenciesTest::removeVersionSuffix).collect(Collectors.toSet()); + if (!moduleNames.contains(graal)) { + fail("Missing Graal (%s):%n%s", graal, proc.preserveArgfile()); + } + if (moduleNames.contains(nativeImage)) { + fail("Native Image API (%s) should not be a dependency of Graal (%s):%n%s", nativeImage, graal, proc.preserveArgfile()); + } + + proc = run(javaExe, + "--limit-modules=jdk.graal.compiler", + "-XX:+EagerJVMCI", + "-Djdk.graal.ShowConfiguration=info", + "--version"); + Pattern expect = Pattern.compile("^Using .* loaded from class files"); + if (proc.output.stream().noneMatch(line -> expect.matcher(line).find())) { + fail("Did not find line matching %s%n%s", expect, proc.preserveArgfile()); + } + } +} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java new file mode 100644 index 000000000000..d4dff8c3d349 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.graal.compiler.hotspot.test; + +import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.code.CompilationResult; +import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.nodes.AllocaNode; +import jdk.graal.compiler.nodes.StructuredGraph; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.word.WordTypes; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.meta.JavaValue; +import org.junit.Test; + +import jdk.graal.compiler.nodes.ValueNode; +import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Regression test for JDK-8351036. Tests that stack offsets > Short.MAX_VALUE can be used. + */ +public class StackSlotLimitTest extends HotSpotGraalCompilerTest { + + /** + * Returns the address of an on-stack buffer. Intrinsified by + * {@link #registerInvocationPlugins}. + * + * @return non-zero value + */ + public static long alloca(int size) { + return 0xFFFFL + size; + } + + static boolean hasStackSlotWithLargeOffset(CompilationResult res) { + for (var info : res.getInfopoints()) { + if (info.debugInfo != null) { + for (var frame = info.debugInfo.frame(); frame != null; frame = frame.caller()) { + for (JavaValue value : frame.values) { + if (value instanceof StackSlot slot) { + int offset = slot.getRawOffset(); + if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { + return true; + } + } + } + } + } + } + return false; + } + + @Override + protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId, OptionValues options) { + CompilationResult res = super.compile(installedCodeOwner, graph, compilationResult, compilationId, options); + if (!hasStackSlotWithLargeOffset(res)) { + // If this fails, then testSnippet1 needs to be updated + throw new AssertionError(String.format("no infopoint containing a stack slot with a non-short offset:%n%s", res.getInfopoints())); + } + return res; + } + + public static boolean testSnippet1() { + long buffer = alloca(Short.MAX_VALUE + 1024); + + // This call seems to reliably produce code with safepoints + // where the frame state includes stack slots with high offsets. + GraalDirectives.opaque(new Exception()); + + return buffer != 0L; + } + + @Test + public void test1() { + // OptionValues options = new OptionValues(getInitialOptions(), HighTier.Options.Inline, + // false); + OptionValues options = getInitialOptions(); + test(options, "testSnippet1"); + } + + @Override + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { + Registration r = new Registration(invocationPlugins, StackSlotLimitTest.class); + r.register(new InvocationPlugin("alloca", int.class) { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + GraalError.guarantee(arg.isConstant(), "%s must be compile-time constant", arg); + WordTypes wordTypes = getProviders().getWordTypes(); + int size = arg.asJavaConstant().asInt(); + AllocaNode alloca = new AllocaNode(wordTypes, size, Byte.BYTES); + b.addPush(wordTypes.getWordKind(), alloca); + return true; + } + }); + super.registerInvocationPlugins(invocationPlugins); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java index 1dc4e9a2e218..84591a27b563 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWatchDog.java @@ -31,9 +31,8 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import org.graalvm.nativeimage.ImageInfo; - import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.core.common.util.Util; import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.options.Option; @@ -336,7 +335,7 @@ private static ScheduledExecutorService createExecutor(ThreadFactory factory) { public static CompilationWatchDog watch(CompilationIdentifier compilation, OptionValues options, boolean singleShotExecutor, EventHandler eventHandler, ThreadFactory factory) { int delay = Options.CompilationWatchDogStartDelay.getValue(options); - if (ImageInfo.inImageBuildtimeCode() && !Options.CompilationWatchDogStartDelay.hasBeenSet(options)) { + if (NativeImageSupport.inBuildtimeCode() && !Options.CompilationWatchDogStartDelay.hasBeenSet(options)) { // Disable watch dog by default when building a native image delay = 0; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java index 11f37c45c5da..6ed08eb90c53 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java @@ -25,10 +25,12 @@ package jdk.graal.compiler.core.common; import org.graalvm.collections.EconomicMap; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; import java.io.PrintStream; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.Map; @@ -44,6 +46,16 @@ */ public interface LibGraalSupport { + /** + * Denotes that the annotated element (type, method, or field) is only visible when running + * hosted on HotSpot (i.e., jargraal or while building libgraal) but not cannot be used at + * libgraal run time. This annotation is ignored when building a non-libgraal native image. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) + @interface HostedOnly { + } + /** * Prefix to use for an image runtime system property describing some aspect of the libgraal * image configuration. These properties are included in the output of @@ -70,7 +82,7 @@ public interface LibGraalSupport { * @param initialValue the initial value of the off-heap word * @return a supplier of the address of the off-heap word */ - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly Supplier createGlobal(long initialValue); /** @@ -95,7 +107,7 @@ public interface LibGraalSupport { /** * Enqueues pending {@link Reference}s into their corresponding {@link ReferenceQueue}s and * executes pending cleaners. - * + *

* If automatic reference handling is enabled, this method is a no-op. */ void processReferences(); @@ -142,19 +154,21 @@ public interface LibGraalSupport { void shutdown(String callbackClassName, String callbackMethodName); /** - * Non-null iff accessed in the context of the libgraal class loader or if executing in the + * Returns true if the current runtime is in the libgraal native image (i.e. SVM). + */ + static boolean inLibGraalRuntime() { + return false; + } + + /** + * Non-null iff accessed in the context of the libgraal class loader or executing in the * libgraal runtime. */ LibGraalSupport INSTANCE = Init.init(); /** - * @return true iff called from classes loaded by the libgraal class loader or if executing in - * the libgraal runtime + * Initializaton support for {@link LibGraalSupport#INSTANCE}. */ - static boolean inLibGraal() { - return INSTANCE != null; - } - class Init { @SuppressWarnings("try") static LibGraalSupport init() { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/NativeImageSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/NativeImageSupport.java new file mode 100644 index 000000000000..34177dab34e0 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/NativeImageSupport.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.core.common; + +/** + * Utility class to retrieve the Native Image context in which code gets executed. + *

+ * This mirrors parts of {@code org.graalvm.nativeimage.ImageInfo} without adding a dependency on + * the latter. + */ +public final class NativeImageSupport { + + /** + * Returns {@code ImageInfo.inImageBuildtimeCode()} if {@code org.graalvm.nativeimage.ImageInfo} + * is available via reflection otherwise false. + */ + private static boolean inImageBuildtimeCode() { + try { + Class c; + try { + c = Class.forName("org.graalvm.nativeimage.ImageInfo"); + } catch (ClassNotFoundException e) { + return false; + } + return (boolean) c.getDeclaredMethod("inImageBuildtimeCode").invoke(null); + } catch (Throwable t) { + throw new InternalError(t); + } + } + + private static final boolean BUILDTIME = inImageBuildtimeCode(); + + /** + * Returns true if (at the time of the call) code is executing in the context of image building. + */ + public static boolean inBuildtimeCode() { + return BUILDTIME; + } + + /** + * Returns true if (at the time of the call) code is executing at image runtime. This method + * will be const-folded. It can be used to hide parts of an application that only work when + * running as native image. + */ + public static boolean inRuntimeCode() { + return false; + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java index f5166335d057..97e8611de962 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/util/CompilationAlarm.java @@ -27,8 +27,6 @@ import java.util.Arrays; import java.util.concurrent.TimeUnit; -import org.graalvm.nativeimage.ImageInfo; - import jdk.graal.compiler.core.common.PermanentBailoutException; import jdk.graal.compiler.core.common.util.EventCounter.EventCounterMarker; import jdk.graal.compiler.debug.Assertions; @@ -63,8 +61,7 @@ public static class Options { // @formatter:on } - public static final boolean LOG_PROGRESS_DETECTION = !ImageInfo.inImageRuntimeCode() && - Boolean.parseBoolean(GraalServices.getSavedProperty("debug." + CompilationAlarm.class.getName() + ".logProgressDetection")); + public static final boolean LOG_PROGRESS_DETECTION = Boolean.parseBoolean(GraalServices.getSavedProperty("debug." + CompilationAlarm.class.getName() + ".logProgressDetection")); /** * The previously installed alarm. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java index 6495ca921b36..03788e05da65 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java @@ -39,6 +39,7 @@ import java.nio.file.StandardOpenOption; import java.util.function.Supplier; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.debug.DebugOptions.PrintGraphTarget; import jdk.graal.compiler.options.OptionValues; @@ -102,7 +103,7 @@ WritableByteChannel channel() throws IOException { if (target == PrintGraphTarget.File) { sharedChannel = createFileChannel(pathProvider, null); } else if (target == PrintGraphTarget.Network) { - if (GraalServices.isInLibgraal() && !ENABLE_NETWORK_DUMPING) { + if (NativeImageSupport.inRuntimeCode() && !ENABLE_NETWORK_DUMPING) { if (!networkDumpingUnsupportedWarned) { // Ignore races or multiple isolates - an extra warning is ok networkDumpingUnsupportedWarned = true; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java index 404f5a874b63..2a89991a918e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeClass.java @@ -50,6 +50,7 @@ import jdk.graal.compiler.core.common.FieldIntrospection; import jdk.graal.compiler.core.common.Fields; import jdk.graal.compiler.core.common.FieldsScanner; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.CounterKey; import jdk.graal.compiler.debug.DebugContext; @@ -69,8 +70,6 @@ import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodeinfo.Verbosity; import jdk.internal.misc.Unsafe; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * Metadata for every {@link Node} type. The metadata includes: @@ -89,7 +88,7 @@ public final class NodeClass extends FieldIntrospection { /** * Gets the {@link NodeClass} associated with a given {@link Class}. */ - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public static NodeClass create(Class c) { assert getUnchecked(c) == null; Class superclass = c.getSuperclass(); @@ -101,7 +100,7 @@ public static NodeClass create(Class c) { } @SuppressWarnings("unchecked") - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly private static NodeClass getUnchecked(Class clazz) { try { Field field = clazz.getDeclaredField("TYPE"); @@ -112,7 +111,7 @@ private static NodeClass getUnchecked(Class clazz) { } } - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public static NodeClass get(Class clazz) { NodeClass result = getUnchecked(clazz); if (result == null && clazz != NODE_CLASS) { @@ -150,13 +149,13 @@ public static NodeClass get(Class clazz) { private final int leafId; - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public NodeClass(Class clazz, NodeClass superNodeClass) { this(clazz, superNodeClass, null, 0); } @SuppressWarnings("try") - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly private NodeClass(Class clazz, NodeClass superNodeClass, int[] presetIterableIds, int presetIterableId) { super(clazz); DebugContext debug = DebugContext.forCurrentThread(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index 979383ba0dee..4ae6a8ed0cb4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -228,7 +228,7 @@ protected ExceptionAction lookupAction(OptionValues values, Throwable cause) { */ private static boolean shouldExitVM(Throwable throwable) { // If not in libgraal, don't exit - if (!LibGraalSupport.inLibGraal()) { + if (LibGraalSupport.INSTANCE == null) { return false; } // If assertions are not enabled, don't exit. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java index 1be113b5b13c..ffef728cb93f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java @@ -36,11 +36,10 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; import jdk.graal.compiler.core.common.Fields; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass; @@ -64,7 +63,7 @@ * {@link jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.Stubs#initStubs} * */ -@Platforms(Platform.HOSTED_ONLY.class) +@LibGraalSupport.HostedOnly public class CompilerConfig { /** 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 d9c252eea4a8..82434d15f406 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 @@ -33,6 +33,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.serviceprovider.LibGraalService; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.core.Instrumentation; @@ -53,7 +54,6 @@ import jdk.vm.ci.code.Architecture; import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import org.graalvm.nativeimage.ImageInfo; /** * A factory that creates the {@link CompilerConfiguration} the compiler will use. Each factory must @@ -275,7 +275,7 @@ public static CompilerConfigurationFactory selectFactory(String name, OptionValu * loaded from. */ private Object getLoadedFromLocation(boolean verbose) { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { String justification = "properties initialized via org.graalvm.nativeimage.hosted.RuntimeSystemProperties " + "are not accessible via GraalServices.getSavedProperties()"; String settings = GraalServices.getSystemProperties(justification).entrySet().stream()// 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 3385eb8a43fa..926d33f01eaa 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 @@ -26,12 +26,12 @@ import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.util.concurrent.ConcurrentHashMap; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.UnmodifiableEconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -212,7 +212,7 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod data = graphDatas.get(methodKey(method)); } if (data == null) { - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport } else { return null; @@ -230,7 +230,7 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod declaringClass = replacements.getProviders().getMetaAccess().lookupJavaType(Object.class); } SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, data.originalMethod, declaringClass); - return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, inImageRuntimeCode()); + return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, LibGraalSupport.inLibGraalRuntime()); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @@ -306,7 +306,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.getProviders().getSnippetReflection(); - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); } parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); 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 2efce55f74ad..6de9b4658a13 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 @@ -584,7 +584,6 @@ private boolean checkNullAllocationStubs() { // This flag indicates that support for loom is enabled. public final boolean continuationsEnabled = getFieldValue("CompilerToVM::Data::continuations_enabled", Boolean.class, "bool"); - // If the nmethod_entry_barrier field is non-null then an entry barrier must be emitted public final int threadDisarmedOffset = getFieldValue("CompilerToVM::Data::thread_disarmed_guard_value_offset", Integer.class, "int"); public final long nmethodEntryBarrier = getFieldValue("CompilerToVM::Data::nmethod_entry_barrier", Long.class, "address"); @@ -746,6 +745,7 @@ protected boolean check() { } } + assert nmethodEntryBarrier != 0L; assert codeEntryAlignment > 0 : codeEntryAlignment; assert checkNullAllocationStubs(); return true; 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 ad5baecba878..47f3dd750bad 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -25,11 +25,12 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.core.ArchitectureSpecific; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.DebugContext; @@ -110,7 +111,7 @@ protected HotSpotReplacementsImpl createReplacements(TargetDescription target, H } protected ClassfileBytecodeProvider createBytecodeProvider(MetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection) { - return new ClassfileBytecodeProvider(metaAccess, snippetReflection); + return inRuntimeCode() ? null : new ClassfileBytecodeProvider(metaAccess, snippetReflection); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, HotSpotWordTypes wordTypes) { @@ -135,9 +136,10 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - if (inImageCode()) { + if (inBuildtimeCode() || inRuntimeCode()) { SnippetSignature.initPrimitiveKindCache(jvmci.getMetaAccess()); } + HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache(); TargetDescription target = codeCache.getTarget(); MetaAccessProvider metaAccess = new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); @@ -202,7 +204,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, bytecodeProvider); providers = replacements.getProviders(); - if (inImageBuildtimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { replacements.maybeInitializeEncoder(); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBytecodeParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBytecodeParser.java index 618a217d45e4..f08c532b2c59 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBytecodeParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBytecodeParser.java @@ -24,9 +24,8 @@ */ package jdk.graal.compiler.hotspot; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; - import jdk.graal.compiler.api.replacements.Snippet; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.PermanentBailoutException; import jdk.graal.compiler.java.BytecodeParser; import jdk.graal.compiler.java.GraphBuilderPhase.Instance; @@ -85,7 +84,7 @@ protected boolean applyInvocationPlugin(CallTargetNode.InvokeKind invokeKind, Va if (plugin instanceof GeneratedNodeIntrinsicInvocationPlugin nodeIntrinsicPlugin) { // Snippets are never parsed in libgraal, and they are the root of the compilation // in jargraal, so check the root method for the Snippet annotation. - if (inImageRuntimeCode() || graph.method().getAnnotation(Snippet.class) == null) { + if (LibGraalSupport.inLibGraalRuntime() || graph.method().getAnnotation(Snippet.class) == null) { throw new PermanentBailoutException(BAD_NODE_INTRINSIC_PLUGIN_CONTEXT + nodeIntrinsicPlugin.getSource().getSimpleName()); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java index 122efa543d07..50e374dac719 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -27,7 +27,7 @@ import java.util.BitSet; import java.util.List; -import org.graalvm.nativeimage.ImageInfo; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; @@ -348,13 +348,15 @@ class Stubs { */ private static final EconomicMap STUBS = EconomicMap.create(); + /** + * Racy between isolates but as stated in {@link #STUBS} javadoc, it's not a problem in + * practice. + */ static HotSpotForeignCallLinkageImpl.CodeInfo getCodeInfo(Stub stub, Backend backend) { ForeignCallSignature sig = stub.getLinkage().getDescriptor().getSignature(); GlobalAtomicLong data = getStubData(sig); long codeInfoInMemory = data.get(); if (codeInfoInMemory == 0L) { - // Racy between isolates but as stated in STUBS javadoc, it's not - // a problem in practice. HotSpotForeignCallLinkageImpl.CodeInfo codeInfo = new HotSpotForeignCallLinkageImpl.CodeInfo(stub.getCode(backend).getStart(), stub.getDestroyedCallerRegisters()); data.set(codeInfo.toMemory()); return codeInfo; @@ -365,7 +367,7 @@ static HotSpotForeignCallLinkageImpl.CodeInfo getCodeInfo(Stub stub, Backend bac private static GlobalAtomicLong getStubData(ForeignCallSignature sig) { GlobalAtomicLong data; - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { data = STUBS.get(sig); GraalError.guarantee(data != null, "missing global data for %s", sig); } else { @@ -388,23 +390,8 @@ private static GlobalAtomicLong getStubData(ForeignCallSignature sig) { public static void initStubs(List sigs) { GraalError.guarantee(STUBS.isEmpty(), "cannot re-initialize STUBS: %s", STUBS); for (ForeignCallSignature sig : sigs) { - initStub(sig); - } - } - - /** - * Creates an entry in the map for avoiding duplicate {@code RuntimeStub}s for {@code sig} - * if no entry currently exists. - * - * @return {@code true} if an entry was added by this call, {@code false} if an entry - * already existed - */ - public static boolean initStub(ForeignCallSignature sig) { - if (!STUBS.containsKey(sig)) { STUBS.put(sig, new GlobalAtomicLong("STUB_" + sig.getName(), 0L)); - return true; } - return false; } } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java index d158ef846d43..6bb24817b00c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -25,15 +25,12 @@ package jdk.graal.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.io.PrintStream; -import org.graalvm.nativeimage.ImageInfo; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.api.runtime.GraalRuntime; -import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.options.Option; @@ -96,7 +93,7 @@ private void ensureInitialized() { @Override public void onSelection() { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { // When instantiating a JVMCI runtime in the libgraal heap there's no // point in delaying HotSpotGraalRuntime initialization as it // is very fast (it's compiled and does no class loading) and will @@ -127,7 +124,7 @@ private void initialize() { } private static void initializeGraalCompilePolicyFields(OptionValues options) { - compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options) && !inImageRuntimeCode(); + compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options) && !LibGraalSupport.inLibGraalRuntime(); String optionValue = Options.GraalCompileOnly.getValue(options); if (optionValue != null) { MethodFilter filter = MethodFilter.parse(optionValue); @@ -167,11 +164,6 @@ static class Options { @Override public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { - if (inImageBuildtimeCode() && inImageRuntimeCode()) { - // A bunch of code assumes that at most one of these conditions - // is true so verify that here. - throw new GraalError("Invariant violation: inImageBuildtimeCode && inImageRuntimeCode must not both be true"); - } HotSpotJVMCIRuntime hsRuntime = (HotSpotJVMCIRuntime) runtime; checkUnsafeAccess(hsRuntime); ensureInitialized(); @@ -203,7 +195,7 @@ public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { * Exit the VM now if {@code jdk.internal.misc.Unsafe} is not accessible. */ private void checkUnsafeAccess(HotSpotJVMCIRuntime hsRuntime) { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { // Access checks were performed when building libgraal. return; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java index 9a53f9694780..437c4a9c6b60 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java @@ -40,7 +40,6 @@ import jdk.graal.compiler.options.OptionsParser; import jdk.vm.ci.common.InitTimer; -import org.graalvm.collections.EconomicSet; /** * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The @@ -159,11 +158,6 @@ private static String stripPrefix(String name, String prefix) { return baseName; } - /** - * The set of libgraal options seen on the command line. - */ - static EconomicSet explicitOptions = EconomicSet.create(); - private static OptionValues initializeOptions() { EconomicMap, Object> values = parseOptions(); OptionValues options = new OptionValues(values); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java index ef87b6b285a2..5ad611c52257 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServiceThread.java @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.hotspot; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -41,7 +42,7 @@ public HotSpotGraalServiceThread(Runnable runnable) { @Override public final void run() { try { - if (GraalServices.isInLibgraal()) { + if (LibGraalSupport.inLibGraalRuntime()) { if (!HotSpotJVMCIRuntime.runtime().attachCurrentThread(isDaemon(), null)) { throw new InternalError("Couldn't attach to HotSpot runtime"); } @@ -55,7 +56,7 @@ public final void run() { try { runnable.run(); } finally { - if (GraalServices.isInLibgraal()) { + if (LibGraalSupport.inLibGraalRuntime()) { HotSpotJVMCIRuntime.runtime().detachCurrentThread(false); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServices.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServices.java index c7d9c10b8482..e4ad7a61e72b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServices.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalServices.java @@ -30,6 +30,7 @@ import java.util.BitSet; import java.util.Objects; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotObjectConstantScope; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -38,7 +39,6 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; -import org.graalvm.nativeimage.ImageInfo; /** * Interface to HotSpot specific functionality that abstracts over which JDK version Graal is @@ -121,7 +121,7 @@ public static CompilationContext openLocalCompilationContext(Object description) * This exists so that the HotSpot VM can be exited from within libgraal. */ public static void exit(int status, HotSpotJVMCIRuntime runtime) { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { runtime.exitHotSpot(status); } else { System.exit(status); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 976ec5afc0d7..7b2eb9983f28 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -24,8 +24,8 @@ */ package jdk.graal.compiler.hotspot; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.util.BitSet; @@ -34,6 +34,7 @@ import jdk.graal.compiler.bytecode.Bytecode; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeSourcePosition; @@ -63,8 +64,6 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * Filters certain method substitutions based on whether there is underlying hardware support for @@ -73,7 +72,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl { public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider bytecodeProvider, TargetDescription target) { super(new GraalDebugHandlersFactory(providers.getSnippetReflection()), providers, bytecodeProvider, target); - if (inImageBuildtimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -81,7 +80,7 @@ public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider byte HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(new GraalDebugHandlersFactory(replacements.getProviders().getSnippetReflection()), providers, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); - if (inImageBuildtimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -91,7 +90,7 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public SymbolicSnippetEncoder maybeInitializeEncoder() { synchronized (HotSpotReplacementsImpl.class) { if (snippetEncoder == null) { @@ -103,7 +102,7 @@ public SymbolicSnippetEncoder maybeInitializeEncoder() { @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { if (method.getAnnotation(HotSpotOperation.class) != null) { return HotSpotWordOperationPlugin.class; } @@ -113,7 +112,7 @@ public Class getIntrinsifyingPlugin(ResolvedJavaMe @Override public void registerConditionalPlugin(InvocationPlugin plugin) { - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { if (snippetEncoder != null) { snippetEncoder.registerConditionalPlugin(plugin); } @@ -122,7 +121,7 @@ public void registerConditionalPlugin(InvocationPlugin plugin) { @Override public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { if (b.parsingIntrinsic() && snippetEncoder != null) { if (getIntrinsifyingPlugin(method) != null) { snippetEncoder.addDelayedInvocationPluginMethod(method); @@ -188,15 +187,15 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo // When assertions are enabled, these fields are used to ensure all snippets are // registered during Graal initialization which in turn ensures that native image // building will not miss any snippets. - @Platforms(Platform.HOSTED_ONLY.class)// + @LibGraalSupport.HostedOnly// private EconomicSet registeredSnippets; - @Platforms(Platform.HOSTED_ONLY.class)// + @LibGraalSupport.HostedOnly// private boolean snippetRegistrationClosed; @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (inImageBuildtimeCode()) { + if (inBuildtimeCode()) { assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); @@ -206,7 +205,7 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin @Override public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { return getEncodedSnippets().getSnippetParameterInfo(method); } return super.getSnippetParameterInfo(method); @@ -214,7 +213,7 @@ public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @Override public boolean isSnippet(ResolvedJavaMethod method) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { return getEncodedSnippets().isSnippet(method); } return super.isSnippet(method); @@ -222,7 +221,7 @@ public boolean isSnippet(ResolvedJavaMethod method) { @Override public void closeSnippetRegistration() { - if (inImageBuildtimeCode()) { + if (inBuildtimeCode()) { snippetRegistrationClosed = true; } } @@ -234,26 +233,26 @@ public static EncodedSnippets getEncodedSnippets() { return encodedSnippets; } - @Platforms(Platform.HOSTED_ONLY.class)// + @LibGraalSupport.HostedOnly// public static boolean snippetsAreEncoded() { return encodedSnippets != null; } - @Platforms(Platform.HOSTED_ONLY.class)// + @LibGraalSupport.HostedOnly// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; } private static volatile EncodedSnippets encodedSnippets; - @Platforms(Platform.HOSTED_ONLY.class)// + @LibGraalSupport.HostedOnly// private static SymbolicSnippetEncoder snippetEncoder; @SuppressWarnings("try") @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { @@ -265,7 +264,7 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } } - assert !inImageBuildtimeCode() || registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); + assert !inBuildtimeCode() || registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); } @@ -278,16 +277,8 @@ public T getInjectedArgument(Class capability) { return super.getInjectedArgument(capability); } - @Platforms(Platform.HOSTED_ONLY.class) - public ResolvedJavaMethod findSnippetMethod(ResolvedJavaMethod thisMethod) { - if (snippetEncoder == null) { - throw new GraalError("findSnippetMethod called before initialization of Replacements"); - } - return snippetEncoder.findSnippetMethod(thisMethod); - } - public static MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { - if (inImageBuildtimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { return SymbolicSnippetEncoder.noticeTypes(metaAccess); } return metaAccess; 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 3ac8074dd2cf..4373fd196925 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 @@ -24,11 +24,10 @@ */ package jdk.graal.compiler.hotspot; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; - import java.lang.reflect.Executable; import java.lang.reflect.Field; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; @@ -51,7 +50,7 @@ public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { @Override public ResolvedJavaType lookupJavaType(Class clazz) { - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); if (type != null) { return type; @@ -74,7 +73,7 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - if (inImageRuntimeCode() && HotSpotReplacementsImpl.isGraalClass(clazz)) { + if (LibGraalSupport.inLibGraalRuntime() && 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; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java index 1ae3e75dcb68..f33cf65bf669 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java @@ -24,13 +24,11 @@ */ package jdk.graal.compiler.hotspot; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; - import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import java.util.Objects; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.meta.Assumptions; @@ -57,7 +55,7 @@ */ public final class SnippetResolvedJavaType implements ResolvedJavaType { private final Class javaClass; - private List methods; + private SnippetResolvedJavaMethod[] methods; private SnippetResolvedJavaType arrayOfType; public SnippetResolvedJavaType(Class javaClass) { @@ -69,20 +67,22 @@ public void setArrayOfType(SnippetResolvedJavaType arrayOfType) { this.arrayOfType = arrayOfType; } + @LibGraalSupport.HostedOnly synchronized SnippetResolvedJavaMethod add(SnippetResolvedJavaMethod method) { - if (inImageRuntimeCode()) { - throw new InternalError("immutable"); - } if (methods == null) { - methods = new ArrayList<>(1); + methods = new SnippetResolvedJavaMethod[]{method}; + return method; } - // This in inefficient but is only use during image building for a small number of methods. - int index = methods.indexOf(method); + // This in inefficient but is only used while building + // libgraal for a small number of methods. + int index = Arrays.asList(methods).indexOf(method); if (index == -1) { - methods.add(method); + SnippetResolvedJavaMethod[] newMethods = Arrays.copyOf(methods, methods.length + 1); + newMethods[methods.length] = method; + methods = newMethods; return method; } else { - return methods.get(index); + return methods[index]; } } @@ -315,7 +315,7 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { if (methods == null) { return new ResolvedJavaMethod[0]; } - return methods.toArray(new ResolvedJavaMethod[0]); + return methods.clone(); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java index 48981a5995aa..af86c64b3b1d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java @@ -36,7 +36,6 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; @@ -49,6 +48,7 @@ import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.type.AbstractObjectStamp; import jdk.graal.compiler.core.common.type.ObjectStamp; @@ -134,8 +134,6 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.UnresolvedJavaType; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * This class performs graph encoding using {@link GraphEncoder} but also converts JVMCI type and @@ -144,7 +142,7 @@ *

* An instance of this class only exist when building libgraal. */ -@Platforms(Platform.HOSTED_ONLY.class) +@LibGraalSupport.HostedOnly public class SymbolicSnippetEncoder { /** @@ -479,9 +477,8 @@ ResolvedJavaMethod findSnippetMethod(ResolvedJavaMethod method) { JavaConstant mirror = originalReplacements.getProviders().getConstantReflection().asJavaClass(type); Class clazz = originalReplacements.getProviders().getSnippetReflection().asObject(Class.class, mirror); SnippetResolvedJavaType snippetType = lookupSnippetType(clazz); - assert (snippetType != null); - SnippetResolvedJavaMethod m = new SnippetResolvedJavaMethod(snippetType, method); - return snippetType.add(m); + GraalError.guarantee(snippetType != null, "missing snippet type for %s", clazz.getName()); + return snippetType.add(new SnippetResolvedJavaMethod(snippetType, method)); } private void ensureSnippetTypeAvailable(ResolvedJavaType type) { @@ -540,12 +537,7 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic lookupSnippetType(SnippetTemplate.EagerSnippetInfo.class); lookupSnippetType(ForeignCallStub.class); - // Ensure AbstractForeignCallStub.getGraph is available - MetaAccessProvider metaAccess = originalReplacements.getProviders().getMetaAccess(); - ResolvedJavaMethod[] stubMethods = metaAccess.lookupJavaType(AbstractForeignCallStub.class).getDeclaredMethods(); - Optional abstractForeignCallStubGetName = Arrays.stream(stubMethods).filter(resolvedJavaMethod -> resolvedJavaMethod.getName().equals("getGraph")).findFirst(); - GraalError.guarantee(abstractForeignCallStubGetName.isPresent(), "ResolvedJavaMethod for AbstractForeignCallStub.getGraph() unavailable"); - findSnippetMethod(abstractForeignCallStubGetName.get()); + registerAbstractForeignCallStubInfo(); SnippetObjectFilter filter = new SnippetObjectFilter(originalReplacements.getProviders()); byte[] snippetEncoding = encoder.getEncoding(); @@ -559,6 +551,14 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic return new EncodedSnippets(snippetEncoding, snippetObjects, encoder.getNodeClasses(), graphDatas, snippetTypes); } + /** + * Ensures the snippet types and methods for {@link AbstractForeignCallStub} are registered. + */ + private void registerAbstractForeignCallStubInfo() { + MetaAccessProvider metaAccess = originalReplacements.getProviders().getMetaAccess(); + findSnippetMethod(AbstractForeignCallStub.getGraphMethod(metaAccess)); + } + /** * Encode any outstanding graphs and return true if any work was done. */ @@ -687,42 +687,43 @@ private Object filterSnippetObject(DebugContext debug, Object o) { if (cached != null) { return cached; } - if (o instanceof HotSpotResolvedJavaMethod) { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) o; + if (o instanceof HotSpotResolvedJavaMethod method) { if (HotSpotReplacementsImpl.isGraalClass(method.getDeclaringClass())) { ResolvedJavaMethod snippetMethod = findSnippetMethod(method); cachedFilteredObjects.put(method, snippetMethod); return snippetMethod; } return filterMethod(debug, method); - } else if (o instanceof HotSpotResolvedJavaField) { - return filterField(debug, (HotSpotResolvedJavaField) o); + } else if (o instanceof HotSpotResolvedJavaField field) { + return filterField(debug, field); } else if (o instanceof HotSpotResolvedJavaType) { return filterType(debug, (HotSpotResolvedJavaType) o); - } else if (o instanceof FieldLocationIdentity) { - FieldLocationIdentity fli = (FieldLocationIdentity) o; + } else if (o instanceof FieldLocationIdentity fli) { if (fli.getField() instanceof HotSpotResolvedJavaField) { return filterFieldLocationIdentity(debug, (HotSpotResolvedJavaField) fli.getField()); } else { return o; } - } else if (o instanceof HotSpotObjectConstant) { - return new SnippetObjectConstant(getSnippetReflection().asObject(Object.class, (HotSpotObjectConstant) o)); + } else if (o instanceof HotSpotObjectConstant constant) { + return new SnippetObjectConstant(getSnippetReflection().asObject(Object.class, constant)); } else if (o instanceof NodeSourcePosition) { // Filter these out for now. These can't easily be handled because these positions // description snippet methods which might not be available in the runtime. return null; - } else if (o instanceof ForeignCallsProvider || o instanceof GraalHotSpotVMConfig || o instanceof WordTypes || o instanceof TargetDescription || + } else if (o instanceof ForeignCallsProvider || + o instanceof GraalHotSpotVMConfig || + o instanceof WordTypes || + o instanceof TargetDescription || o instanceof SnippetReflectionProvider) { // These objects should be recovered from the runtime environment instead of being // embedded in the node. throw new GraalError("%s shouldn't be reachable from snippets", o); - } else if (o instanceof Stamp) { - return filterStamp(debug, (Stamp) o); - } else if (o instanceof StampPair) { - return filterStampPair(debug, (StampPair) o); - } else if (o instanceof ResolvedJavaMethodBytecode) { - return filterBytecode(debug, (ResolvedJavaMethodBytecode) o); + } else if (o instanceof Stamp stamp) { + return filterStamp(debug, stamp); + } else if (o instanceof StampPair stampPair) { + return filterStampPair(debug, stampPair); + } else if (o instanceof ResolvedJavaMethodBytecode m) { + return filterBytecode(debug, m); } return o; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index cca478783101..3946d2b9dca8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -241,7 +241,7 @@ public void enter(CompilationResultBuilder crb) { rawEnter(crb, frameMap, masm, config, isStub); crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); - if (!isStub && config.nmethodEntryBarrier != 0) { + if (!isStub) { emitNmethodEntryBarrier(crb, masm); } if (entryPointDecorator != null) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java index a25cac73fb79..dc8e370b5528 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -164,7 +164,7 @@ public void enter(CompilationResultBuilder crb) { assert frameMap.getRegisterConfig().getCalleeSaveRegisters() == null; - if (!isStub && config.nmethodEntryBarrier != 0) { + if (!isStub) { emitNmethodEntryBarrier(crb, asm); } else { crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java index 2f2bf07b1fce..d53be0fce953 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/debug/BenchmarkCounters.java @@ -39,6 +39,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.graal.compiler.debug.CSVUtil; import jdk.graal.compiler.debug.GraalError; @@ -52,7 +53,6 @@ import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import org.graalvm.nativeimage.ImageInfo; //JaCoCo Exclude @@ -464,7 +464,7 @@ protected void patternFound(int index) { enabled = true; } if (Options.TimedDynamicCounters.getValue(options) > 0) { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { throw new GraalError("Use of %s is only supported in jargraal", Options.TimedDynamicCounters.getName()); } Thread thread = new Thread(new Runnable() { 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 5150e20cf3a7..8c0894477611 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 @@ -35,7 +35,6 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import static org.graalvm.word.LocationIdentity.any; import java.util.Arrays; @@ -48,6 +47,7 @@ import jdk.graal.compiler.core.common.CompressEncoding; import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.calc.Condition; import jdk.graal.compiler.core.common.memory.BarrierType; @@ -1035,8 +1035,8 @@ public static final class RuntimeCalls { } private void throwCachedException(BytecodeExceptionNode node) { - if (inImageRuntimeCode()) { - throw new InternalError("Can't throw exception from SVM object"); + if (LibGraalSupport.inLibGraalRuntime()) { + throw new InternalError("Cannot throw exception from libgraal (JDK-8306085)"); } Throwable exception = Exceptions.cachedExceptions.get(node.getExceptionKind()); assert exception != null; 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 28981887d807..39640cd8fb4e 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 @@ -52,7 +52,6 @@ import static jdk.graal.compiler.nodes.ProfileData.BranchProbabilityData.injected; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.lang.annotation.Annotation; import java.lang.invoke.ConstantCallSite; @@ -66,11 +65,11 @@ import java.math.BigInteger; import java.util.zip.CRC32; -import org.graalvm.nativeimage.ImageInfo; import org.graalvm.word.LocationIdentity; import jdk.graal.compiler.api.directives.GraalDirectives; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.calc.Condition; import jdk.graal.compiler.core.common.memory.BarrierType; import jdk.graal.compiler.core.common.memory.MemoryOrderMode; @@ -234,7 +233,7 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, Plugins plugins = new Plugins(invocationPlugins); plugins.appendNodePlugin(new HotSpotExceptionDispatchPlugin(config, wordTypes.getWordKind())); StandardGraphBuilderPlugins.registerConstantFieldLoadPlugin(plugins); - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { // In libgraal all word related operations have been fully processed so this is unneeded HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, constantReflection, wordTypes, barrierSet); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin); @@ -289,7 +288,7 @@ public void run() { } }); - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { // In libgraal, all NodeIntrinsics have already been converted into nodes. NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); invocationPlugins.defer(() -> { @@ -729,7 +728,8 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec r.register(new InlineOnlyInvocationPlugin("setCurrentThread", Receiver.class, Thread.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode thread) { - GraalError.guarantee(ImageInfo.inImageRuntimeCode() || isAnnotatedByChangesCurrentThread(b.getMethod()), "method changes current Thread but is not annotated ChangesCurrentThread"); + GraalError.guarantee(LibGraalSupport.inLibGraalRuntime() || isAnnotatedByChangesCurrentThread(b.getMethod()), + "method changes current Thread but is not annotated ChangesCurrentThread"); try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) { receiver.get(true); CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(helper.getWordKind())); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index c56482f0840c..af5eb71859c8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -97,8 +97,6 @@ import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TANH; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import static org.graalvm.word.LocationIdentity.any; import java.util.EnumMap; @@ -106,6 +104,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.word.LocationIdentity; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; @@ -140,9 +139,9 @@ import jdk.graal.compiler.replacements.nodes.AESNode; import jdk.graal.compiler.replacements.nodes.ArrayCompareToForeignCalls; import jdk.graal.compiler.replacements.nodes.ArrayCopyWithConversionsForeignCalls; -import jdk.graal.compiler.replacements.nodes.ArrayFillNode; import jdk.graal.compiler.replacements.nodes.ArrayEqualsForeignCalls; import jdk.graal.compiler.replacements.nodes.ArrayEqualsWithMaskForeignCalls; +import jdk.graal.compiler.replacements.nodes.ArrayFillNode; import jdk.graal.compiler.replacements.nodes.ArrayIndexOfForeignCalls; import jdk.graal.compiler.replacements.nodes.ArrayRegionCompareToForeignCalls; import jdk.graal.compiler.replacements.nodes.BigIntegerMulAddNode; @@ -364,7 +363,7 @@ private void registerStubCallFunctions(OptionValues options, HotSpotProviders pr } registerForeignCall(INVOKE_STATIC_METHOD_ONE_ARG, invokeJavaMethodAddress, NativeCall); - if (!inImageRuntimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime()) { /* * These functions are only used for testing purposes but their registration also * ensures that libgraal has support for InvokeJavaMethodStub built into the image, @@ -549,12 +548,7 @@ public void initialize(HotSpotProviders providers, OptionValues options) { registerForeignCall(NOTIFY, c.notifyAddress, NativeCall); registerForeignCall(NOTIFY_ALL, c.notifyAllAddress, NativeCall); - if (c.nmethodEntryBarrier != 0) { - registerForeignCall(NMETHOD_ENTRY_BARRIER, c.nmethodEntryBarrier, NativeCall); - } else if (inImageBuildtimeCode()) { - // Ensure this is known to libgraal - register(NMETHOD_ENTRY_BARRIER.getSignature()); - } + registerForeignCall(NMETHOD_ENTRY_BARRIER, c.nmethodEntryBarrier, NativeCall); linkStackOnlyForeignCall(c.gc == Z, options, providers, Z_LOAD_BARRIER, c.zBarrierSetRuntimeLoadBarrierOnOopFieldPreloaded, DONT_PREPEND_THREAD); linkStackOnlyForeignCall(c.gc == Z, options, providers, Z_STORE_BARRIER_WITHOUT_HEALING, c.zBarrierSetRuntimeStoreBarrierOnOopFieldWithoutHealing, DONT_PREPEND_THREAD); 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 492e7bf99397..8510629ebeff 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 @@ -31,6 +31,7 @@ import java.util.Objects; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -47,7 +48,6 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.nativeimage.ImageInfo; public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider { @@ -63,7 +63,7 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { - if (ImageInfo.inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); // This can only be a compiler object when in libgraal. return new SnippetObjectConstant(object); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java index 980a8e575877..00d056958ed6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java @@ -58,7 +58,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; -import org.graalvm.nativeimage.ImageInfo; /** * A {@linkplain #getGraph generated} stub for a {@link Transition non-leaf} foreign call from @@ -194,7 +193,7 @@ protected final Object debugScopeContext() { * return getAndClearObjectResult(thread()); * } * - * + *

* If the stub returns a primitive or word, the graph created corresponds to this pseudo code * (using {@code int} as the primitive return type): * @@ -207,7 +206,7 @@ protected final Object debugScopeContext() { * return result; * } * - * + *

* If the stub is void, the graph created corresponds to this pseudo code: * *

@@ -218,7 +217,7 @@ protected final Object debugScopeContext() {
      *         }
      *     }
      * 
- * + *

* In each example above, the {@code currentThread} argument is the C++ JavaThread value (i.e., * %r15 on AMD64) and is only prepended if {@link #prependThread} is true. */ @@ -233,7 +232,7 @@ protected final StructuredGraph getGraph(DebugContext debug, CompilationIdentifi ForeignCallSnippets.Templates foreignCallSnippets = lowerer.getForeignCallSnippets(); ResolvedJavaMethod handlePendingException = foreignCallSnippets.handlePendingException.getMethod(); ResolvedJavaMethod getAndClearObjectResult = foreignCallSnippets.getAndClearObjectResult.getMethod(); - ResolvedJavaMethod thisMethod = getGraphMethod(); + ResolvedJavaMethod thisMethod = getGraphMethod(providers.getMetaAccess()); HotSpotGraphKit kit = new HotSpotGraphKit(debug, thisMethod, providers, providers.getGraphBuilderPlugins(), compilationId, toString(), false, true); StructuredGraph graph = kit.getGraph(); graph.getGraphState().forceDisableFrameStateVerification(); @@ -261,26 +260,20 @@ protected final StructuredGraph getGraph(DebugContext debug, CompilationIdentifi protected abstract boolean shouldClearException(); - private ResolvedJavaMethod getGraphMethod() { - ResolvedJavaMethod thisMethod = null; - MetaAccessProvider metaAccess = providers.getMetaAccess(); + /** + * Gets the {@link ResolvedJavaMethod} object representing + * {@link #getGraph(DebugContext, CompilationIdentifier)}. + */ + public static ResolvedJavaMethod getGraphMethod(MetaAccessProvider metaAccess) { + ResolvedJavaMethod candidate = null; for (ResolvedJavaMethod method : metaAccess.lookupJavaType(AbstractForeignCallStub.class).getDeclaredMethods(false)) { if (method.getName().equals("getGraph")) { - if (thisMethod == null) { - thisMethod = method; - } else { - throw new InternalError("getGraph is ambiguous"); - } + GraalError.guarantee(candidate == null, "Multiple getGraph methods found: %s and %s", method, candidate); + candidate = method; } } - if (thisMethod == null) { - throw new InternalError("Can't find " + getClass().getSimpleName() + ".getGraph"); - } - if (ImageInfo.inImageBuildtimeCode()) { - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); - replacements.findSnippetMethod(thisMethod); - } - return thisMethod; + GraalError.guarantee(candidate != null, "Missing method %s.getGraph", AbstractForeignCallStub.class.getName()); + return candidate; } protected ParameterNode[] createParameters(GraphKit kit) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java index 9a7988561b5d..da960aab56f1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java @@ -25,9 +25,9 @@ package jdk.graal.compiler.hotspot.stubs; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.graph.Node; @@ -89,7 +89,7 @@ public void inlineAsIntrinsic(Invoke invoke, String reason, String phase) { GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); StructuredGraph calleeGraph; - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { calleeGraph = getReplacements().getSnippet(method, null, null, null, false, null, invokeNode.getOptions()); } else { calleeGraph = new StructuredGraph.Builder(invokeNode.getOptions(), invokeNode.getDebug()).method(method).trackNodeSourcePosition( diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java index 9f4b69fa043f..1faa7140e1d5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java @@ -39,6 +39,7 @@ import jdk.graal.compiler.core.CompilationPrinter; import jdk.graal.compiler.core.common.CompilationIdentifier; import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugContext.Builder; @@ -79,8 +80,6 @@ import jdk.vm.ci.meta.DefaultProfilingInfo; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.TriState; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; //JaCoCo Exclude @@ -170,7 +169,7 @@ public RegisterConfig getRegisterConfig() { * Calls {@link #getGraph} for the side effect of registering the types used in the graph with * SymbolicSnippetEncoder.snippetTypes. */ - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public final void findTypesInGraph() { try (DebugContext debug = DebugContext.disabled(options)) { Stub stub = linkage.getStub(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java index 6ddd48991c17..2cf5b6e280fc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/BytecodeParser.java @@ -237,6 +237,8 @@ import static jdk.graal.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode; import static jdk.graal.compiler.core.common.GraalOptions.StrictDeoptInsertionChecks; import static jdk.graal.compiler.core.common.GraalOptions.TraceInlining; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.core.common.type.StampFactory.objectNonNull; import static jdk.graal.compiler.debug.GraalError.shouldNotReachHereUnexpectedValue; import static jdk.graal.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing; @@ -256,8 +258,6 @@ import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.util.ArrayList; import java.util.Arrays; @@ -2737,8 +2737,9 @@ protected final void notifyAfterInline(ResolvedJavaMethod inlinedMethod) { * intrinsic) can be inlined. */ protected boolean canInlinePartialIntrinsicExit() { - assert !inImageRuntimeCode(); - return InlinePartialIntrinsicExitDuringParsing.getValue(options) && !inImageBuildtimeCode() && method.getAnnotation(Snippet.class) == null; + assert !inRuntimeCode(); + return InlinePartialIntrinsicExitDuringParsing.getValue(options) && !inBuildtimeCode() && + method.getAnnotation(Snippet.class) == null; } private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) { @@ -2773,7 +2774,6 @@ private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod i * @param format a format string * @param args arguments to the format string */ - protected void traceWithContext(String format, Object... args) { StackTraceElement where = code.asStackTraceElement(bci()); String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), @@ -2918,11 +2918,9 @@ protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallT protected void genReturn(ValueNode returnVal, JavaKind returnKind) { if (parsingIntrinsic() && returnVal != null) { - if (returnVal instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) returnVal; + if (returnVal instanceof StateSplit stateSplit) { FrameState stateAfter = stateSplit.stateAfter(); if (stateSplit.hasSideEffect()) { - assert stateSplit != null; if (stateAfter.bci == BytecodeFrame.AFTER_BCI) { assert stateAfter.hasExactlyOneUsage(); assert stateAfter.usages().first() == stateSplit : Assertions.errorMessage(stateAfter, stateSplit); @@ -2934,10 +2932,11 @@ protected void genReturn(ValueNode returnVal, JavaKind returnKind) { // without a return value on the top of stack. assert stateSplit instanceof Invoke : Assertions.errorMessage(stateSplit); ResolvedJavaMethod targetMethod = ((Invoke) stateSplit).getTargetMethod(); - if (!inImageRuntimeCode()) { - assert targetMethod != null; - assert (targetMethod.getAnnotation(Fold.class) != null || targetMethod.getAnnotation(Node.NodeIntrinsic.class) != null) : "Target should be fold or intrinsic " + - targetMethod; + if (!inRuntimeCode()) { + GraalError.guarantee(targetMethod != null, "%s has null target method", stateSplit); + GraalError.guarantee(targetMethod.getAnnotation(Fold.class) != null || + targetMethod.getAnnotation(Node.NodeIntrinsic.class) != null, + "Target should be fold or intrinsic ", targetMethod); } state = new FrameState(BytecodeFrame.AFTER_BCI); } else { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRInstructionClass.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRInstructionClass.java index f5e2bb783c2d..1892f252d315 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRInstructionClass.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRInstructionClass.java @@ -31,6 +31,7 @@ import jdk.graal.compiler.core.common.Fields; import jdk.graal.compiler.core.common.FieldsScanner; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.lir.LIRInstruction.OperandFlag; @@ -40,12 +41,10 @@ import jdk.graal.compiler.lir.StandardOp.ValueMoveOp; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.Value; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; public class LIRInstructionClass extends LIRIntrospection { - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public static LIRInstructionClass create(Class c) { return new LIRInstructionClass<>(c); } @@ -66,7 +65,7 @@ public static LIRInstructionClass create(Class private final String opcodeConstant; private final int opcodeIndex; - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public LIRInstructionClass(Class clazz) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); @@ -95,7 +94,7 @@ public LIRInstructionClass(Class clazz) { } @SuppressWarnings("unchecked") - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly public static LIRInstructionClass get(Class clazz) { try { Field field = clazz.getDeclaredField("TYPE"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/asm/CompilationResultBuilderFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/asm/CompilationResultBuilderFactory.java index 1961822f91ac..30453117a973 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/asm/CompilationResultBuilderFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/asm/CompilationResultBuilderFactory.java @@ -34,6 +34,7 @@ import jdk.graal.compiler.asm.Assembler; import jdk.graal.compiler.code.CompilationResult; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.lir.LIR; @@ -45,7 +46,6 @@ import jdk.graal.compiler.options.OptionType; import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.code.Register; -import org.graalvm.nativeimage.ImageInfo; /** * Factory class for creating {@link CompilationResultBuilder}s. @@ -76,7 +76,7 @@ CompilationResultBuilder createBuilder(CoreProviders providers, */ CompilationResultBuilderFactory Default = new CompilationResultBuilderFactory() { - private List lirInstructionVerifiers = new ArrayList<>(); + private final List lirInstructionVerifiers = new ArrayList<>(); private volatile boolean isVerifierInitialized = false; private void initializeLIRVerifiers(String lirInstructionVerifierPath) { @@ -104,13 +104,16 @@ public CompilationResultBuilder createBuilder(CoreProviders providers, CompilationResult compilationResult, Register uncompressedNullRegister, LIR lir) { - if (ImageInfo.inImageRuntimeCode()) { - // LIR instruction verifier uses URLClassLoader which is excluded from - // libgraal due to the image size increase it causes. + String lirInstructionVerifierPath = Options.LIRInstructionVerifierPath.getValue(options); + if (NativeImageSupport.inRuntimeCode()) { + if (lirInstructionVerifierPath != null) { + // LIR instruction verifier uses URLClassLoader which is excluded from + // native images due to the image size increase it causes. + throw new IllegalArgumentException(Options.LIRInstructionVerifierPath.getName() + " is not supported in native image"); + } } else if (!isVerifierInitialized) { synchronized (lirInstructionVerifiers) { if (!isVerifierInitialized) { - String lirInstructionVerifierPath = Options.LIRInstructionVerifierPath.getValue(options); if (lirInstructionVerifierPath != null && !lirInstructionVerifierPath.isEmpty()) { initializeLIRVerifiers(lirInstructionVerifierPath); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/IfNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/IfNode.java index 29fe4c7c250f..da6681dd1fe8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/IfNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/IfNode.java @@ -104,6 +104,23 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL private static final CounterKey CORRECTED_PROBABILITIES = DebugContext.counter("CorrectedProbabilities"); + /** + * Number of {@link IfNode}'s {@linkplain NodeClass#getSuccessorEdges() successor edges}. + */ + public static final long SUCCESSOR_EDGES_COUNT = TYPE.getSuccessorEdges().getCount(); + + /** + * Index of the {@link #trueSuccessor} in {@link IfNode}'s + * {@linkplain NodeClass#getSuccessorEdges() successor edges}. + */ + public static final long TRUE_SUCCESSOR_EDGE_INDEX = TYPE.getSuccessorEdges().getIndex(IfNode.class, "trueSuccessor"); + + /** + * Index of the {@link #falseSuccessor} in {@link IfNode}'s + * {@linkplain NodeClass#getSuccessorEdges() successor edges}. + */ + public static final long FALSE_SUCCESSOR_EDGE_INDEX = TYPE.getSuccessorEdges().getIndex(IfNode.class, "falseSuccessor"); + @Successor AbstractBeginNode trueSuccessor; @Successor AbstractBeginNode falseSuccessor; @Input(InputType.Condition) LogicNode condition; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/SimplifyingGraphDecoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/SimplifyingGraphDecoder.java index 843c88608135..efa52f853ca0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/SimplifyingGraphDecoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/SimplifyingGraphDecoder.java @@ -258,16 +258,10 @@ protected Node canonicalizeFixedNode(MethodScope methodScope, LoopScope loopScop } } - /** - * Number of {@link IfNode} successor edges. - */ - private static final long IF_NODE_SUCCESSORS_COUNT = 2L; - static { - /* Check assumptions made by earlyCanonicalization about IfNode. */ + /* Check assumption made by earlyCanonicalization about IfNode. */ Edges edges = IfNode.TYPE.getSuccessorEdges(); - GraalError.guarantee(edges.getDirectCount() == IF_NODE_SUCCESSORS_COUNT, "%s expected to have 2 direct successors", IfNode.class); - GraalError.guarantee(edges.getCount() == IF_NODE_SUCCESSORS_COUNT, "%s expected to have 0 indirect successors", IfNode.class); + GraalError.guarantee(edges.getCount() == IfNode.SUCCESSOR_EDGES_COUNT, "%s expected to have 0 indirect successors", IfNode.class); /* Check assumptions made by earlyCanonicalization about IntegerSwitchNode. */ edges = IntegerSwitchNode.TYPE.getSuccessorEdges(); @@ -279,15 +273,14 @@ protected Node canonicalizeFixedNode(MethodScope methodScope, LoopScope loopScop protected boolean earlyCanonicalization(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) { if (node instanceof IfNode ifNode && ifNode.condition() instanceof LogicConstantNode condition) { - Edges edges = ifNode.getNodeClass().getSuccessorEdges(); - long survivingIndex = edges.getIndex(IfNode.class, condition.getValue() ? "trueSuccessor" : "falseSuccessor"); + long survivingIndex = condition.getValue() ? IfNode.TRUE_SUCCESSOR_EDGE_INDEX : IfNode.FALSE_SUCCESSOR_EDGE_INDEX; /* Read the surviving successor order id. */ long successorsByteIndex = methodScope.reader.getByteIndex(); methodScope.reader.setByteIndex(successorsByteIndex + survivingIndex * methodScope.orderIdWidth); int survivingOrderId = readOrderId(methodScope); // Reset decode position to first byte after successors - methodScope.reader.setByteIndex(successorsByteIndex + (IF_NODE_SUCCESSORS_COUNT * methodScope.orderIdWidth)); + methodScope.reader.setByteIndex(successorsByteIndex + (IfNode.SUCCESSOR_EDGES_COUNT * methodScope.orderIdWidth)); removeSplit(methodScope, loopScope, ifNode, survivingOrderId); return true; @@ -301,9 +294,8 @@ protected boolean earlyCanonicalization(MethodScope methodScope, LoopScope loopS long survivingIndex = switchNode.successorIndexAtKey(value); /* Read the surviving successor order id. */ - Edges edges = switchNode.getNodeClass().getSuccessorEdges(); long size = methodScope.reader.getSVInt(); - long successorsIndex = edges.getIndex(SwitchNode.class, "successors"); + long successorsIndex = SwitchNode.SUCCESSORS_EDGE_INDEX; long successorsByteIndex = methodScope.reader.getByteIndex() + successorsIndex * methodScope.orderIdWidth; methodScope.reader.setByteIndex(successorsByteIndex + survivingIndex * methodScope.orderIdWidth); int survivingOrderId = readOrderId(methodScope); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/SwitchNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/SwitchNode.java index e2509eb396e8..3202540fe2e5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/SwitchNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/SwitchNode.java @@ -77,6 +77,12 @@ public abstract class SwitchNode extends ControlSplitNode { protected final int[] keySuccessors; protected SwitchProbabilityData profileData; + /** + * Index of the {@link #successors} field in {@link SwitchNode}'s + * {@linkplain NodeClass#getSuccessorEdges() successor edges}. + */ + public static final long SUCCESSORS_EDGE_INDEX = TYPE.getSuccessorEdges().getIndex(SwitchNode.class, "successors"); + /** * Constructs a new Switch. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java index a1cb9eaa91b6..6040773e6698 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java @@ -24,8 +24,8 @@ */ package jdk.graal.compiler.nodes.graphbuilderconf; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -79,7 +79,7 @@ public String getSourceLocation() { * @return true if the folding being attempted by the caller can proceed */ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, ResolvedJavaMethod foldAnnotatedMethod) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { // In native image runtime compilation, there is no later stage where execution of the // plugin can be deferred. return true; @@ -93,7 +93,7 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re return false; } - if (inImageBuildtimeCode()) { + if (inBuildtimeCode()) { // Calls to the @Fold method from the generated fold plugin shouldn't be folded. This is // detected by comparing the class names of the current plugin and the method being // parsed. These might be in different class loaders so the classes can't be compared diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/IntrinsicContext.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/IntrinsicContext.java index 8248982d1f9f..551a81158157 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/IntrinsicContext.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/IntrinsicContext.java @@ -81,7 +81,6 @@ public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, this.originalMethod = method; this.intrinsicMethod = intrinsic; this.bytecodeProvider = bytecodeProvider; - assert bytecodeProvider != null; this.compilationContext = compilationContext; this.allowPartialIntrinsicArgumentMismatch = allowPartialIntrinsicArgumentMismatch; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugin.java index c3c6ee77415b..b807423be54b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugin.java @@ -24,7 +24,7 @@ */ package jdk.graal.compiler.nodes.graphbuilderconf; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -386,7 +386,7 @@ public String getSourceLocation() { return String.format("%s.%s()", m.getDeclaringClass().getName(), m.getName()); } } - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { return String.format("%s.%s()", c.getName(), "apply"); } throw new GraalError("could not find method named \"apply\" or \"defaultHandler\" in " + c.getName()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java index 6d65a1d083a4..0c666da8da77 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -26,8 +26,8 @@ import static java.lang.String.format; import static jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins.LateClassPlugins.CLOSED_LATE_CLASS_PLUGIN; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -163,7 +163,7 @@ public static class OptionalLazySymbol implements Type { @SuppressWarnings("this-escape") public OptionalLazySymbol(String name) { this.name = name; - if (inImageBuildtimeCode()) { + if (inBuildtimeCode()) { resolve(); } } @@ -178,7 +178,7 @@ public String getTypeName() { * resolution fails. */ public Class resolve() { - if (!inImageRuntimeCode() && resolved == null) { + if (!inRuntimeCode() && resolved == null) { Class resolvedOrNull = resolveClass(name, true); resolved = resolvedOrNull == null ? MASK_NULL : resolvedOrNull; } @@ -324,8 +324,8 @@ public void register(InvocationPlugin plugin) { } invocationPlugins.add(plugin); - assert inImageRuntimeCode() || Checks.check(this.plugins, declaringType, plugin); - assert inImageRuntimeCode() || Checks.checkResolvable(declaringType, plugin); + assert inRuntimeCode() || Checks.check(this.plugins, declaringType, plugin); + assert inRuntimeCode() || Checks.checkResolvable(declaringType, plugin); } @Override @@ -807,8 +807,8 @@ protected void register(Type declaringClass, InvocationPlugin plugin, boolean al plugin.rewriteReceiverType(declaringClass); } put(declaringClass, plugin, allowOverwrite); - assert inImageRuntimeCode() || Checks.check(this, declaringClass, plugin); - assert inImageRuntimeCode() || Checks.checkResolvable(declaringClass, plugin); + assert inRuntimeCode() || Checks.check(this, declaringClass, plugin); + assert inRuntimeCode() || Checks.checkResolvable(declaringClass, plugin); } /** @@ -1018,7 +1018,7 @@ public boolean maybePrintIntrinsics(OptionValues options) { long isolateID = IsolateUtil.getIsolateID(); if (PRINTING_ISOLATE.get() == isolateID || PRINTING_ISOLATE.compareAndSet(0, isolateID)) { synchronized (PRINTING_ISOLATE) { - if (inImageRuntimeCode() && PrintedIntrinsics == null) { + if (inRuntimeCode() && PrintedIntrinsics == null) { PrintedIntrinsics = new HashSet<>(); } UnmodifiableMapCursor> entries = getInvocationPlugins(false, true).getEntries(); @@ -1064,11 +1064,11 @@ private static final class Checks { static final Class[][] SIGS; static { - if (!Assertions.assertionsEnabled() && !inImageBuildtimeCode()) { + if (!Assertions.assertionsEnabled() && !inBuildtimeCode()) { throw new GraalError("%s must only be used in assertions", Checks.class.getName()); } ArrayList[]> sigs = new ArrayList<>(MAX_ARITY); - if (!inImageRuntimeCode()) { + if (!inRuntimeCode()) { for (Method method : InvocationPlugin.class.getDeclaredMethods()) { if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { Class[] sig = method.getParameterTypes(); @@ -1203,7 +1203,7 @@ public static Class resolveType(Type type, boolean optional) { if (type instanceof OptionalLazySymbol) { return ((OptionalLazySymbol) type).resolve(); } - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { throw new GraalError("Unresolved type in native image image:" + type.getTypeName()); } return resolveClass(type.getTypeName(), optional); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java index 397d10fde824..9c34940c829c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/SnippetParameterInfo.java @@ -24,7 +24,7 @@ */ package jdk.graal.compiler.nodes.spi; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import java.util.ArrayList; import java.util.BitSet; @@ -83,7 +83,7 @@ public SnippetParameterInfo(ResolvedJavaMethod method) { this.varargsParametersBits = varargs; this.nonNullParametersBits = nonNull; - if (inImageBuildtimeCode()) { + if (inBuildtimeCode()) { // Capture the names during image building in case the image wants them. initNames(method, count); } else { 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 2ca22282012d..fed060d8fd49 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.options; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; - import java.util.ArrayList; import java.util.Collection; import java.util.Formatter; @@ -66,23 +64,23 @@ public static LibGraalOptionsInfo create() { /** * Compiler options info available in libgraal. */ - public static final LibGraalOptionsInfo libgraalOptions = LibGraalSupport.inLibGraal() ? LibGraalOptionsInfo.create() : null; + public static final LibGraalOptionsInfo libgraalOptions = LibGraalSupport.INSTANCE != null ? LibGraalOptionsInfo.create() : null; /** * Gets an iterable of available {@link OptionDescriptors}. */ @ExcludeFromJacocoGeneratedReport("contains libgraal-only path") public static Iterable getOptionsLoader() { - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { return List.of(new OptionDescriptorsMap(Objects.requireNonNull(libgraalOptions.descriptors, "missing options"))); } - if (LibGraalSupport.inLibGraal()) { + if (LibGraalSupport.INSTANCE != null) { /* * Executing in the context of the libgraal class loader so use it to load the * OptionDescriptors. */ - ClassLoader myCL = OptionsParser.class.getClassLoader(); - return ServiceLoader.load(OptionDescriptors.class, myCL); + ClassLoader libgraalLoader = OptionsParser.class.getClassLoader(); + return ServiceLoader.load(OptionDescriptors.class, libgraalLoader); } else { /* * The Graal module (i.e., jdk.graal.compiler) is loaded by the platform class loader. @@ -226,14 +224,13 @@ public static void parseOption(String name, Object uncheckedValue, EconomicMap optionType = desc.getOptionValueType(); Object value; - if (!(uncheckedValue instanceof String)) { + if (!(uncheckedValue instanceof String valueString)) { if (optionType != uncheckedValue.getClass()) { String type = optionType.getSimpleName(); throw new IllegalArgumentException(type + " option '" + desc.getName() + "' must have " + type + " value, not " + uncheckedValue.getClass() + " [toString: " + uncheckedValue + "]"); } value = uncheckedValue; } else { - String valueString = (String) uncheckedValue; if (optionType == Boolean.class) { if ("true".equals(valueString)) { value = Boolean.TRUE; @@ -360,7 +357,7 @@ public static boolean collectFuzzyMatches(Iterable toSearch, String name, } static boolean isEnterpriseOption(OptionDescriptor desc) { - if (inImageRuntimeCode()) { + if (LibGraalSupport.inLibGraalRuntime()) { if (libgraalOptions == null) { return false; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/CanonicalizerPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/CanonicalizerPhase.java index 608feaafb3ca..40572802513e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/CanonicalizerPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/CanonicalizerPhase.java @@ -544,11 +544,9 @@ public static boolean gvn(Node node, NodeClass nodeClass) { } public boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) { - if (Options.CanonicalizerVerifyGVNAllowed.getValue(node.getOptions())) { - assert ((StructuredGraph) node.graph()).getGraphState().isBeforeStage( - StageFlag.PARTIAL_REDUNDANCY_SCHEDULE) : "GVN must not occur after expanding partially redundant nodes, trying to gvn " + node + " for graph " + - node.graph(); - } + assert !Options.CanonicalizerVerifyGVNAllowed.getValue(node.getOptions()) || ((StructuredGraph) node.graph()).getGraphState().isBeforeStage( + StageFlag.PARTIAL_REDUNDANCY_SCHEDULE) : "GVN must not occur after expanding partially redundant nodes, trying to gvn " + node + " for graph " + + node.graph(); return gvn(node, nodeClass); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/CachingPEGraphDecoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/CachingPEGraphDecoder.java index 9820b2e8dc07..e74c0576f5c8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/CachingPEGraphDecoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/CachingPEGraphDecoder.java @@ -24,7 +24,7 @@ */ package jdk.graal.compiler.replacements; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; @@ -120,7 +120,7 @@ public CachingPEGraphDecoder(Architecture architecture, private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider) { CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); StructuredGraph graphToEncode; - if (graph.isSubstitution() && inImageRuntimeCode()) { + if (graph.isSubstitution() && inRuntimeCode()) { throw GraalError.shouldNotReachHere("dead path"); // ExcludeFromJacocoGeneratedReport } else { graphToEncode = buildGraph(method, intrinsicBytecodeProvider, canonicalizer); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/GraphKit.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/GraphKit.java index 07fa25931c31..73b03c24b714 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/GraphKit.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/GraphKit.java @@ -24,9 +24,9 @@ */ package jdk.graal.compiler.replacements; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.nodes.CallTargetNode.InvokeKind.Static; import static jdk.vm.ci.code.BytecodeFrame.UNKNOWN_BCI; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -317,7 +317,7 @@ protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, Res * {@code method} */ public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { // The dynamic lookup needed for this code is unsupported return true; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java index 47fdae86d08f..83928c42afc2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java @@ -25,13 +25,12 @@ package jdk.graal.compiler.replacements; import static jdk.graal.compiler.core.common.GraalOptions.UseSnippetGraphCache; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static jdk.graal.compiler.debug.DebugOptions.DumpOnError; import static jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static jdk.graal.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; -import static org.graalvm.nativeimage.ImageInfo.inImageCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import java.util.BitSet; import java.util.concurrent.ConcurrentHashMap; @@ -88,7 +87,6 @@ import jdk.graal.compiler.phases.common.DeadCodeEliminationPhase; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.replacements.arraycopy.ArrayCopyForeignCalls; -import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.graal.compiler.word.Word; import jdk.graal.compiler.word.WordOperationPlugin; import jdk.graal.compiler.word.WordTypes; @@ -177,7 +175,7 @@ public Stamp getInjectedStamp(Class type) { @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { - if (!inImageRuntimeCode()) { + if (!inRuntimeCode()) { if (method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null) { return GeneratedInvocationPlugin.class; } @@ -205,7 +203,7 @@ public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod m // Force inlining when parsing replacements return createIntrinsicInlineInfo(method, defaultBytecodeProvider); } else { - assert inImageCode() || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", + assert inRuntimeCode() || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), method.format("%h.%n"), b); } @@ -479,8 +477,8 @@ static class EncodedIntrinsicContext extends IntrinsicContext { @Override public boolean isDeferredInvoke(StateSplit stateSplit) { - if (GraalServices.isInLibgraal()) { - throw GraalError.shouldNotReachHere("unused in libgraal"); // ExcludeFromJacocoGeneratedReport + if (inRuntimeCode()) { + throw GraalError.shouldNotReachHere("unused in native image"); // ExcludeFromJacocoGeneratedReport } if (stateSplit instanceof Invoke invoke) { ResolvedJavaMethod method = invoke.callTarget().targetMethod(); @@ -539,10 +537,7 @@ protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider } IntrinsicContext initialIntrinsicContext = null; - Snippet snippetAnnotation = null; - if (!inImageRuntimeCode()) { - snippetAnnotation = method.getAnnotation(Snippet.class); - } + Snippet snippetAnnotation = !inRuntimeCode() ? method.getAnnotation(Snippet.class) : null; if (snippetAnnotation == null) { // Post-parse inlined intrinsic initialIntrinsicContext = new EncodedIntrinsicContext(substitutedMethod, method, bytecodeProvider, context, false); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java index 5da058bf1f76..7f3a60b24557 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java @@ -25,13 +25,13 @@ package jdk.graal.compiler.replacements; import static java.util.FormattableFlags.ALTERNATE; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.debug.DebugContext.applyFormattingFlagsAndWidth; import static jdk.graal.compiler.debug.DebugOptions.DumpOnError; import static jdk.graal.compiler.graph.iterators.NodePredicates.isNotA; import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import static jdk.graal.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; import static org.graalvm.word.LocationIdentity.any; import java.lang.reflect.Array; @@ -966,7 +966,7 @@ protected SnippetInfo snippet(Providers providers, } providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options), options); LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations; - if (inImageRuntimeCode() || GraalOptions.EagerSnippets.getValue(options)) { + if (inRuntimeCode() || GraalOptions.EagerSnippets.getValue(options)) { SnippetParameterInfo snippetParameterInfo = providers.getReplacements().getSnippetParameterInfo(javaMethod); return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver, snippetParameterInfo, type); } else { @@ -1532,7 +1532,7 @@ private static ValueNode getDefaultReturnValue(StructuredGraph snippet, Node rep } private static boolean verifyIntrinsicsProcessed(StructuredGraph snippetCopy) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { return true; } for (MethodCallTargetNode target : snippetCopy.getNodes(MethodCallTargetNode.TYPE)) { @@ -2924,12 +2924,12 @@ private static boolean checkTemplate(MetaAccessProvider metaAccess, Arguments ar for (int i = offset; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { JavaKind kind = signature.getParameterKind(i - offset); - assert inImageRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); + assert inRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); } else if (args.info.isVarargsParameter(i)) { assert args.values[i] instanceof Varargs : Assertions.errorMessage(args.values[i], args, method); Varargs varargs = (Varargs) args.values[i]; - assert inImageRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); + assert inRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); } else if (args.info.isNonNullParameter(i)) { assert checkNonNull(method, args.info.getParameterName(i), args.values[i]); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java index e1194f6d3a62..5b3828ca4b08 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java @@ -26,11 +26,11 @@ import jdk.graal.compiler.api.directives.GraalDirectives; import jdk.graal.compiler.api.replacements.Snippet; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.replacements.SnippetTemplate.AbstractTemplates; import jdk.graal.compiler.replacements.SnippetTemplate.SnippetInfo; -import org.graalvm.nativeimage.ImageInfo; /** * A class that lives in the compiler that is full of snippets used for testing. Given that snippets @@ -82,7 +82,7 @@ public static class Templates extends AbstractTemplates { public Templates(OptionValues options, Providers providers) { super(options, providers); - assert !ImageInfo.inImageRuntimeCode() : "This code must only be used in jargraal unittests"; + assert LibGraalSupport.INSTANCE == null : "This code must only be used in jargraal unittests"; producer = snippet(providers, TransplantTestSnippets.class, "producer", Snippet.SnippetType.TRANSPLANTED_SNIPPET); producerWithArgs = snippet(providers, TransplantTestSnippets.class, "producerWithArgs", Snippet.SnippetType.TRANSPLANTED_SNIPPET); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/Classfile.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/Classfile.java index fcb2e9d3d85f..8100cd8f9550 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/Classfile.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/Classfile.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.List; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.replacements.classfile.ClassfileConstant.Utf8; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -43,6 +44,7 @@ * @see Constant * Pool */ +@LibGraalSupport.HostedOnly public class Classfile { private final ResolvedJavaType type; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecode.java index 89740a1fb603..85223ec306b8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecode.java @@ -30,6 +30,7 @@ import jdk.graal.compiler.bytecode.Bytecode; import jdk.graal.compiler.bytecode.BytecodeProvider; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.meta.ConstantPool; @@ -44,6 +45,7 @@ * The bytecode properties of a method as parsed directly from a class file without any * instrumentation or other rewriting performed on the bytecode. */ +@LibGraalSupport.HostedOnly public class ClassfileBytecode implements Bytecode { private static final int EXCEPTION_HANDLER_TABLE_SIZE_IN_BYTES = 8; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecodeProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecodeProvider.java index 66012fad2fed..6cab3c388b27 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecodeProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileBytecodeProvider.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; +import jdk.graal.compiler.core.common.LibGraalSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -58,6 +59,7 @@ * avoid this is to have a completely isolated {@code jdk.vm.ci.meta} implementation for parsing * snippet/intrinsic bytecodes. */ +@LibGraalSupport.HostedOnly public final class ClassfileBytecodeProvider implements BytecodeProvider { private final ClassLoader loader; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstant.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstant.java index 5e71987ff22b..e830b2d4c17f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstant.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstant.java @@ -33,6 +33,7 @@ import java.io.IOException; import jdk.graal.compiler.bytecode.Bytecodes; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.meta.JavaConstant; @@ -40,6 +41,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +@LibGraalSupport.HostedOnly abstract class ClassfileConstant { // @formatter:off diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java index ef0556a1068d..eef8e0457ec2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java @@ -30,6 +30,7 @@ import java.io.DataInputStream; import java.io.IOException; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.replacements.classfile.ClassfileConstant.ClassRef; import jdk.graal.compiler.replacements.classfile.ClassfileConstant.ExecutableRef; @@ -45,6 +46,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Signature; +@LibGraalSupport.HostedOnly class ClassfileConstantPool implements ConstantPool, ConstantPoolPatch { final ClassfileConstant[] entries; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ConstantPoolPatch.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ConstantPoolPatch.java index 5655c4f62b96..e76e7d6b6875 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ConstantPoolPatch.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ConstantPoolPatch.java @@ -24,9 +24,11 @@ */ package jdk.graal.compiler.replacements.classfile; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; +@LibGraalSupport.HostedOnly public interface ConstantPoolPatch { JavaMethod lookupMethod(int index, int opcode, ResolvedJavaMethod caller); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java index 695056dae29e..0f7583c00433 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GlobalAtomicLong.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.serviceprovider; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; + import java.lang.ref.Cleaner; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; @@ -31,9 +33,6 @@ import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.internal.misc.Unsafe; -import org.graalvm.nativeimage.ImageInfo; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * A shareable long value in the JVM process that is updated atomically. The long value is stored in @@ -50,7 +49,7 @@ public class GlobalAtomicLong { /** * Cleaner for freeing {@link #address} when executing in jargraal. */ - @Platforms(Platform.HOSTED_ONLY.class) // + @LibGraalSupport.HostedOnly // private static Cleaner cleaner; /** @@ -82,14 +81,11 @@ public class GlobalAtomicLong { public GlobalAtomicLong(String name, long initialValue) { this.name = name; this.initialValue = initialValue; - if (ImageInfo.inImageRuntimeCode()) { + if (inRuntimeCode()) { throw GraalError.shouldNotReachHere("Cannot create " + getClass().getName() + " objects in native image runtime"); } else { LibGraalSupport libgraal = LibGraalSupport.INSTANCE; if (libgraal != null) { - if (ImageInfo.inImageRuntimeCode()) { - throw GraalError.shouldNotReachHere("The addressSupplier field value should have been replaced at image build time"); - } addressSupplier = libgraal.createGlobal(initialValue); } else { // Executing in jargraal 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 062b05779b94..e1aa5bf8fc82 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 @@ -25,8 +25,7 @@ package jdk.graal.compiler.serviceprovider; import static java.lang.Thread.currentThread; -import static org.graalvm.nativeimage.ImageInfo.inImageBuildtimeCode; -import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.io.IOException; import java.io.InputStream; @@ -41,8 +40,8 @@ import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.vm.ci.code.Architecture; -import org.graalvm.nativeimage.ImageInfo; import jdk.graal.compiler.debug.GraalError; import jdk.internal.misc.VM; @@ -50,29 +49,18 @@ import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.services.Services; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * Interface to functionality that abstracts over which JDK version Graal is running on. */ public final class GraalServices { - /** - * Returns true if current runtime is in libgraal. Note that this is more specific than - * {@link ImageInfo#inImageRuntimeCode()}. The latter will return true when executing any native - * image, not just libgraal. - */ - public static boolean isInLibgraal() { - return Services.IS_IN_NATIVE_IMAGE; - } - /** * The set of services available in libgraal. */ private static final Map, List> libgraalServices; - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly private static Class loadClassOrNull(String name) { try { return GraalServices.class.getClassLoader().loadClass(name); @@ -85,7 +73,7 @@ private static Class loadClassOrNull(String name) { * Gets a name for the current architecture that is compatible with * {@link Architecture#getName()}. */ - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly private static String getJVMCIArch() { String rawArch = getSavedProperty("os.arch"); return switch (rawArch) { @@ -97,7 +85,7 @@ private static String getJVMCIArch() { }; } - @Platforms(Platform.HOSTED_ONLY.class) + @LibGraalSupport.HostedOnly @SuppressWarnings("unchecked") private static void addProviders(String arch, Class service) { List providers = (List) GraalServices.libgraalServices.computeIfAbsent(service, key -> new ArrayList<>()); @@ -133,7 +121,7 @@ private GraalServices() { */ @SuppressWarnings("unchecked") public static Iterable load(Class service) { - if (inImageRuntimeCode() || libgraalServices != null) { + if (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?)", @@ -141,6 +129,10 @@ public static Iterable load(Class service) { } return (Iterable) list; } + if (NativeImageSupport.inRuntimeCode()) { + // Service loading by Graal can only be done at build time + return List.of(); + } return load0(service); } @@ -165,7 +157,7 @@ public static Properties getSystemProperties(String justification) { * @see VM#getSavedProperties */ public static Map getSavedProperties() { - if (inImageBuildtimeCode()) { + if (!LibGraalSupport.inLibGraalRuntime() && LibGraalSupport.INSTANCE != null) { // Avoid calling down to JVMCI native methods as they will fail to // link in a copy of JVMCI loaded by a LibGraalLoader. return jdk.internal.misc.VM.getSavedProperties(); @@ -187,6 +179,7 @@ public static String getSavedProperty(String name) { return getSavedProperties().get(name); } + @LibGraalSupport.HostedOnly private static Iterable load0(Class service) { Module module = GraalServices.class.getModule(); // Graal cannot know all the services used by another module @@ -226,11 +219,8 @@ public void remove() { * * @param other all JVMCI packages will be opened to the module defining this class */ + @LibGraalSupport.HostedOnly static void openJVMCITo(Class other) { - if (inImageRuntimeCode()) { - return; - } - Module jvmciModule = JVMCI_MODULE; Module otherModule = other.getModule(); if (jvmciModule != otherModule) { @@ -283,6 +273,7 @@ public static S loadSingle(Class service, boolean required) { /** * Gets the class file bytes for {@code c}. */ + @LibGraalSupport.HostedOnly public static InputStream getClassfileAsStream(Class c) throws IOException { String classfilePath = c.getName().replace('.', '/') + ".class"; return c.getModule().getResourceAsStream(classfilePath); @@ -303,7 +294,7 @@ public static InputStream getClassfileAsStream(Class c) throws IOException { * trusted code. */ public static boolean isToStringTrusted(Class c) { - if (inImageRuntimeCode()) { + if (inRuntimeCode()) { return true; } diff --git a/sdk/mx.sdk/suite.py b/sdk/mx.sdk/suite.py index 0c0dd69a9b70..ffc8641dd705 100644 --- a/sdk/mx.sdk/suite.py +++ b/sdk/mx.sdk/suite.py @@ -879,6 +879,11 @@ class UniversalDetector { }, "description" : "Native Image API extensions for libgraal.", "maven": { + # Explicitly set the artifactId here instead of relying on mx automatically + # deriving it from the distribution name. This also makes the maven + # coordinates stable in case of the (unlikely) event that the distribution + # is renamed. + "artifactId": "nativeimage-libgraal", "tag": ["default", "public"], }, }, diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index b54a33153edd..a0f144c36dbe 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -266,6 +266,7 @@ import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.common.NativeImageSupport; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.core.common.util.CompilationAlarm; @@ -542,6 +543,8 @@ public void run(Map entryPoints, protected static void setSystemPropertiesForImageEarly() { VMError.guarantee(ImageInfo.inImageBuildtimeCode(), "Expected ImageInfo.inImageBuildtimeCode() to return true"); + VMError.guarantee(ImageInfo.inImageBuildtimeCode() == NativeImageSupport.inBuildtimeCode(), + "ImageInfo.inImageBuildtimeCode() and NativeImageSupport.inBuildtimeCode() are not in sync"); } private static void setSystemPropertiesForImageLate(NativeImageKind imageKind) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java index 68adeb8a6745..f081fe4b9a92 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java @@ -33,8 +33,17 @@ import java.util.LinkedHashSet; import java.util.ServiceLoader; import java.util.Set; +import java.util.random.RandomGenerator; import java.util.stream.Collectors; +import java.util.stream.Stream; +import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; +import jdk.graal.compiler.hotspot.HotSpotBackendFactory; +import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider; +import jdk.graal.compiler.truffle.hotspot.TruffleCallBoundaryInstrumentationFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; @@ -47,6 +56,7 @@ import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionType; +import sun.util.locale.provider.LocaleDataMetaInfo; /** * Support for {@link ServiceLoader} on Substrate VM. @@ -84,30 +94,38 @@ public static class Options { } - private static final Set SKIPPED_SERVICES = Set.of( + private static final Set SKIPPED_SERVICES = Stream.of( // image builder internal ServiceLoader interfaces - "com.oracle.svm.hosted.NativeImageClassLoaderPostProcessing", - "org.graalvm.nativeimage.Platform", + NativeImageClassLoaderPostProcessing.class, + + /* + * NOTE: Platform.class had to be added to this list since our analysis + * discovers that Platform.includedIn is reachable regardless of fact that it is + * constant folded at registerPlatformPlugins method of + * SubstrateGraphBuilderPlugins. This issue hasn't manifested before because + * implementation classes were instantiated using runtime reflection instead of + * ServiceLoader (and thus weren't reachable in analysis). + */ + Platform.class, + /* * Loaded in java.util.random.RandomGeneratorFactory.FactoryMapHolder, which is * initialized at image build time. */ - "java.util.random.RandomGenerator", - "java.security.Provider", // see SecurityServicesFeature - "sun.util.locale.provider.LocaleDataMetaInfo", // see LocaleSubstitutions + RandomGenerator.class, + java.security.Provider.class, // see SecurityServicesFeature + LocaleDataMetaInfo.class, // see LocaleSubstitutions + /* Graal hotspot-specific services */ - "jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory", - "jdk.graal.compiler.hotspot.CompilerConfigurationFactory", - "jdk.graal.compiler.hotspot.HotSpotBackendFactory", - "jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider$Extensions", - "jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider", - "jdk.graal.compiler.truffle.hotspot.TruffleCallBoundaryInstrumentationFactory"); + HotSpotJVMCIBackendFactory.class, + CompilerConfigurationFactory.class, + HotSpotBackendFactory.class, + DefaultHotSpotLoweringProvider.Extensions.class, + HotSpotInvocationPluginProvider.class, + TruffleCallBoundaryInstrumentationFactory.class) - // NOTE: Platform class had to be added to this list since our analysis discovers that - // Platform.includedIn is reachable regardless of fact that it is constant folded at - // registerPlatformPlugins method of SubstrateGraphBuilderPlugins. This issue hasn't manifested - // before because implementation classes were instantiated using runtime reflection instead of - // ServiceLoader (and thus weren't reachable in analysis). + .map(Class::getName) + .collect(Collectors.toUnmodifiableSet()); /** * Services that should not be processed here, for example because they are handled by @@ -116,10 +134,9 @@ public static class Options { private final Set servicesToSkip = new HashSet<>(SKIPPED_SERVICES); private static final Set SKIPPED_PROVIDERS = Set.of( - /* Graal hotspot-specific service-providers */ - "jdk.graal.compiler.hotspot.meta.HotSpotDisassemblerProvider", /* Skip console providers until GR-44085 is fixed */ - "jdk.internal.org.jline.JdkConsoleProviderImpl", "jdk.jshell.execution.impl.ConsoleImpl$ConsoleProviderImpl"); + "jdk.internal.org.jline.JdkConsoleProviderImpl", + "jdk.jshell.execution.impl.ConsoleImpl$ConsoleProviderImpl"); private final Set serviceProvidersToSkip = new HashSet<>(SKIPPED_PROVIDERS); @@ -224,7 +241,7 @@ void handleServiceClassIsReachable(DuringAnalysisAccess access, Class service * the same behavior as using RuntimeReflection.register(nullaryConstructor). In * the first case, the constructor is marked for query purposes only, so this * if-statement cannot be eliminated. - * + * */ RuntimeReflection.register(nullaryConstructor); } else { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/ReachabilityTracePrinter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/ReachabilityTracePrinter.java index cc195628207f..a7ffa25b0492 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/ReachabilityTracePrinter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/ReachabilityTracePrinter.java @@ -59,6 +59,15 @@ public static class Options { public static final HostedOptionKey AbortOnFieldReachable = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build()); } + private static String reportElements(String element, String trace, String reportsPath, String baseImageName, List patterns, + HostedOptionKey option) { + String elements = element + "s"; + Path path = ReportUtils.report("trace for " + elements, reportsPath, "trace_" + elements + "_" + baseImageName, "txt", + writer -> writer.print(trace)); + String argument = SubstrateOptionsParser.commandArgument(option, String.join(",", patterns)); + return "Image building is interrupted as the " + elements + " specified via " + argument + " are reachable. " + PATH_MESSAGE_PREFIX + path + ". "; + } + public static void report(String imageName, OptionValues options, String reportsPath, BigBang bb) { String baseImageName = ReportUtils.extractImageName(imageName); @@ -66,43 +75,25 @@ public static void report(String imageName, OptionValues options, String reports List typePatterns = ReachabilityTracePrinter.Options.AbortOnTypeReachable.getValue(options).values(); if (!typePatterns.isEmpty()) { - StringWriter stringWriter = new StringWriter(); - int count = ReachabilityTracePrinter.printTraceForTypesImpl(typePatterns, bb, new PrintWriter(stringWriter)); - if (count > 0) { - String trace = stringWriter.toString(); - Path path = ReportUtils.report("trace for types", reportsPath, "trace_types_" + baseImageName, "txt", - writer -> writer.print(trace)); - String abortOnTypeReachableOption = SubstrateOptionsParser.commandArgument(Options.AbortOnTypeReachable, String.join(",", typePatterns)); - String message = "Image building is interrupted as the types specified via " + abortOnTypeReachableOption + " are reachable. " + PATH_MESSAGE_PREFIX + path; - consoleMessageBuilder.append(message); + StringWriter buf = new StringWriter(); + if (ReachabilityTracePrinter.printTraceForTypesImpl(typePatterns, bb, new PrintWriter(buf)) > 0) { + consoleMessageBuilder.append(reportElements("type", buf.toString(), reportsPath, baseImageName, typePatterns, Options.AbortOnTypeReachable)); } } List methodPatterns = ReachabilityTracePrinter.Options.AbortOnMethodReachable.getValue(options).values(); if (!methodPatterns.isEmpty()) { - StringWriter stringWriter = new StringWriter(); - int count = ReachabilityTracePrinter.printTraceForMethodsImpl(methodPatterns, bb, new PrintWriter(stringWriter)); - if (count > 0) { - String trace = stringWriter.toString(); - Path path = ReportUtils.report("trace for methods", reportsPath, "trace_methods_" + baseImageName, "txt", - writer -> writer.print(trace)); - String abortOnMethodReachableOption = SubstrateOptionsParser.commandArgument(Options.AbortOnMethodReachable, String.join(",", methodPatterns)); - String message = "Image building is interrupted as the methods specified via " + abortOnMethodReachableOption + " are reachable. " + PATH_MESSAGE_PREFIX + path; - consoleMessageBuilder.append(message); + StringWriter buf = new StringWriter(); + if (ReachabilityTracePrinter.printTraceForMethodsImpl(methodPatterns, bb, new PrintWriter(buf)) > 0) { + consoleMessageBuilder.append(reportElements("method", buf.toString(), reportsPath, baseImageName, methodPatterns, Options.AbortOnMethodReachable)); } } List fieldPatterns = ReachabilityTracePrinter.Options.AbortOnFieldReachable.getValue(options).values(); if (!fieldPatterns.isEmpty()) { - StringWriter stringWriter = new StringWriter(); - int count = ReachabilityTracePrinter.printTraceForFieldsImpl(fieldPatterns, bb, new PrintWriter(stringWriter)); - if (count > 0) { - String trace = stringWriter.toString(); - Path path = ReportUtils.report("trace for fields", reportsPath, "trace_fields_" + baseImageName, "txt", - writer -> writer.print(trace)); - String abortOnFieldReachableOption = SubstrateOptionsParser.commandArgument(Options.AbortOnFieldReachable, String.join(",", fieldPatterns)); - String message = "Image building is interrupted as the fields specified via " + abortOnFieldReachableOption + " are reachable. " + PATH_MESSAGE_PREFIX + path; - consoleMessageBuilder.append(message); + StringWriter buf = new StringWriter(); + if (ReachabilityTracePrinter.printTraceForFieldsImpl(fieldPatterns, bb, new PrintWriter(buf)) > 0) { + consoleMessageBuilder.append(reportElements("field", buf.toString(), reportsPath, baseImageName, fieldPatterns, Options.AbortOnFieldReachable)); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/FactoryMethodSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/FactoryMethodSupport.java index bf0f7f7617dc..a86970b78f29 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/FactoryMethodSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/FactoryMethodSupport.java @@ -92,10 +92,10 @@ public AnalysisMethod lookup(AnalysisMetaAccess aMetaAccess, AnalysisMethod aCon ResolvedJavaType unwrappedReturnType = (throwAllocatedObject ? aMetaAccess.lookupJavaType(void.class) : aInstType).getWrapped(); Signature unwrappedSignature = ResolvedSignature.fromArray(unwrappedParameterTypes, unwrappedReturnType); ResolvedJavaMethod unwrappedConstructor = aConstructor.getWrapped(); - ResolvedJavaType unwrappedInstatiatedType = aInstType.getWrapped(); + ResolvedJavaType unwrappedInstantiatedType = aInstType.getWrapped(); ResolvedJavaType unwrappedDeclaringClass = (aMetaAccess.lookupJavaType(throwAllocatedObject ? FactoryThrowMethodHolder.class : FactoryMethodHolder.class)).getWrapped(); ConstantPool unwrappedConstantPool = unwrappedConstructor.getConstantPool(); - return new FactoryMethod(name, unwrappedConstructor, unwrappedInstatiatedType, unwrappedDeclaringClass, unwrappedSignature, unwrappedConstantPool, throwAllocatedObject); + return new FactoryMethod(name, unwrappedConstructor, unwrappedInstantiatedType, unwrappedDeclaringClass, unwrappedSignature, unwrappedConstantPool, throwAllocatedObject); }); AnalysisMethod aMethod = aMetaAccess.getUniverse().lookup(factoryMethod); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 8c7bef1eb279..edc231c5d6ca 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -38,6 +38,8 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.stream.Stream; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.core.common.NativeImageSupport; import org.graalvm.nativeimage.AnnotationAccess; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; @@ -176,7 +178,9 @@ public class SubstrateGraphBuilderPlugins { - /** Collection of debug options for SubstrateGraphBuilderPlugins. */ + /** + * Collection of debug options for SubstrateGraphBuilderPlugins. + */ public static class Options { @Option(help = "Enable trace logging for dynamic proxy.")// public static final HostedOptionKey DynamicProxyTracing = new HostedOptionKey<>(false); @@ -388,32 +392,44 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec }); } + static final class ImageInfoPlugin extends RequiredInvocationPlugin { + + private final JavaConstant returnValue; + + ImageInfoPlugin(String name, JavaConstant returnValue) { + super(name); + this.returnValue = returnValue; + } + + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + b.push(JavaKind.Boolean, ConstantNode.forConstant(returnValue, b.getMetaAccess(), b.getGraph())); + return true; + } + } + + /** + * @see ImageInfo#inImageCode() + * @see ImageInfo#inImageRuntimeCode() + * @see ImageInfo#inImageBuildtimeCode() + * @see NativeImageSupport#inBuildtimeCode() + * @see NativeImageSupport#inRuntimeCode() + * @see LibGraalSupport#inLibGraalRuntime() + */ private static void registerImageInfoPlugins(InvocationPlugins plugins) { Registration registration = new Registration(plugins, ImageInfo.class); - registration.register(new RequiredInvocationPlugin("inImageCode") { - /** See {@link ImageInfo#inImageCode()}. */ - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(JavaKind.Boolean, ConstantNode.forConstant(JavaConstant.TRUE, b.getMetaAccess(), b.getGraph())); - return true; - } - }); - registration.register(new RequiredInvocationPlugin("inImageBuildtimeCode") { - /** See {@link ImageInfo#inImageBuildtimeCode()}. */ - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(JavaKind.Boolean, ConstantNode.forConstant(JavaConstant.FALSE, b.getMetaAccess(), b.getGraph())); - return true; - } - }); - registration.register(new RequiredInvocationPlugin("inImageRuntimeCode") { - /** See {@link ImageInfo#inImageRuntimeCode()}. */ - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(JavaKind.Boolean, ConstantNode.forConstant(JavaConstant.TRUE, b.getMetaAccess(), b.getGraph())); - return true; - } - }); + registration.register(new ImageInfoPlugin("inImageCode", JavaConstant.TRUE)); + registration.register(new ImageInfoPlugin("inImageBuildtimeCode", JavaConstant.FALSE)); + registration.register(new ImageInfoPlugin("inImageRuntimeCode", JavaConstant.TRUE)); + + registration = new Registration(plugins, NativeImageSupport.class); + registration.register(new ImageInfoPlugin("inBuildtimeCode", JavaConstant.FALSE)); + registration.register(new ImageInfoPlugin("inRuntimeCode", JavaConstant.TRUE)); + + if (!SubstrateOptions.LibGraalClassLoader.getValue().isEmpty()) { + registration = new Registration(plugins, LibGraalSupport.class); + registration.register(new ImageInfoPlugin("inLibGraalRuntime", JavaConstant.TRUE)); + } } private static void registerProxyPlugins(AnnotationSubstitutionProcessor annotationSubstitutions, InvocationPlugins plugins, ParsingReason reason) { @@ -494,11 +510,11 @@ static Class[] extractClassArray(GraphBuilderContext b, AnnotationSubstitutio /** * Try to extract a Class array from a ValueNode. There are two situations: - * + *

* 1. The node is a ConstantNode. Then we get its initial value. However, since Java doesn't * have immutable arrays this method cannot guarantee that the array content will not change. * Therefore, if exact is set to true we return null. - * + *

* 2. The node is a NewArrayNode. Then we track the stores in the array as long as all are * constants and there is no control flow split. If the content of the array cannot be * determined a null value is returned.