From 59235a67a3713219bdce927f05ba46853ae734d8 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 5 Jun 2025 20:25:06 +0200 Subject: [PATCH] Make foreign API support optional in parser --- ..._jdk_internal_misc_ScopedMemoryAccess.java | 15 +++++--------- .../com/oracle/svm/core/ForeignSupport.java | 17 +++++++++++++--- .../phases/SharedGraphBuilderPhase.java | 20 ++++++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java b/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java index 76b0254e77c3..dbf5078e46a8 100644 --- a/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java +++ b/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java @@ -25,12 +25,11 @@ package com.oracle.svm.core.foreign; import java.io.FileDescriptor; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.ref.Reference; import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.ArenaIntrinsics; +import com.oracle.svm.core.ForeignSupport; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.annotate.TargetElement; @@ -100,7 +99,7 @@ static void registerNatives() { @SuppressWarnings("static-method") @Substitute @TargetElement(onlyWith = SharedArenasEnabled.class) - @SVMScoped + @ForeignSupport.Scoped @AlwaysInline("Safepoints must be visible in caller") public void loadInternal(MemorySessionImpl session, MappedMemoryUtilsProxy mappedUtils, long address, boolean isSync, long size) { SubstrateForeignUtil.checkIdentity(mappedUtils, Target_java_nio_MappedMemoryUtils.PROXY); @@ -121,7 +120,7 @@ public void loadInternal(MemorySessionImpl session, MappedMemoryUtilsProxy mappe @SuppressWarnings("static-method") @Substitute @TargetElement(onlyWith = SharedArenasEnabled.class) - @SVMScoped + @ForeignSupport.Scoped @AlwaysInline("Safepoints must be visible in caller") public boolean isLoadedInternal(MemorySessionImpl session, MappedMemoryUtilsProxy mappedUtils, long address, boolean isSync, long size) { SubstrateForeignUtil.checkIdentity(mappedUtils, Target_java_nio_MappedMemoryUtils.PROXY); @@ -143,7 +142,7 @@ public boolean isLoadedInternal(MemorySessionImpl session, MappedMemoryUtilsProx @SuppressWarnings("static-method") @Substitute @TargetElement(onlyWith = SharedArenasEnabled.class) - @SVMScoped + @ForeignSupport.Scoped @AlwaysInline("Safepoints must be visible in caller") public void unloadInternal(MemorySessionImpl session, MappedMemoryUtilsProxy mappedUtils, long address, boolean isSync, long size) { SubstrateForeignUtil.checkIdentity(mappedUtils, Target_java_nio_MappedMemoryUtils.PROXY); @@ -166,7 +165,7 @@ public void unloadInternal(MemorySessionImpl session, MappedMemoryUtilsProxy map @SuppressWarnings("static-method") @Substitute @TargetElement(onlyWith = SharedArenasEnabled.class) - @SVMScoped + @ForeignSupport.Scoped @AlwaysInline("Safepoints must be visible in caller") public void forceInternal(MemorySessionImpl session, MappedMemoryUtilsProxy mappedUtils, FileDescriptor fd, long address, boolean isSync, long index, long length) { SubstrateForeignUtil.checkIdentity(mappedUtils, Target_java_nio_MappedMemoryUtils.PROXY); @@ -215,7 +214,3 @@ void closeScope0Unsupported(Target_jdk_internal_foreign_MemorySessionImpl sessio throw SharedArenasDisabled.fail(); } } - -@Retention(RetentionPolicy.RUNTIME) -@interface SVMScoped { -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ForeignSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ForeignSupport.java index 8d0c0bae5359..c30dbeef029b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ForeignSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ForeignSupport.java @@ -24,6 +24,9 @@ */ package com.oracle.svm.core; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.image.DisallowedImageHeapObjects.DisallowedObjectReporter; @@ -33,9 +36,7 @@ public interface ForeignSupport { @Fold static boolean isAvailable() { - boolean result = ImageSingletons.contains(ForeignSupport.class); - assert result || !SubstrateOptions.isForeignAPIEnabled(); - return result; + return ImageSingletons.contains(ForeignSupport.class); } @Fold @@ -48,4 +49,14 @@ static ForeignSupport singleton() { void onMemorySegmentReachable(Object obj, DisallowedObjectReporter reporter); void onScopeReachable(Object obj, DisallowedObjectReporter reporter); + + /** + * This annotation is used to mark substitution methods that substitute an + * {@code jdk.internal.misc.ScopedMemoryAccess.Scoped}-annotated method. This will signal the + * bytecode parser that special instrumentation support is required. Such substitution methods + * are expected to already have a certain structure. + */ + @Retention(RetentionPolicy.RUNTIME) + @interface Scoped { + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java index 6f93de99b6f4..2e6b6ccb1314 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java @@ -27,7 +27,6 @@ import static com.oracle.svm.core.SubstrateUtil.toUnboxedClass; import static jdk.graal.compiler.bytecode.Bytecodes.LDC2_W; -import java.lang.annotation.Annotation; import java.lang.constant.ConstantDescs; import java.lang.invoke.LambdaConversionException; import java.lang.invoke.MethodHandles; @@ -55,6 +54,7 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.svm.common.meta.MultiMethod; +import com.oracle.svm.core.ForeignSupport; import com.oracle.svm.core.bootstrap.BootstrapMethodConfiguration; import com.oracle.svm.core.bootstrap.BootstrapMethodConfiguration.BootstrapMethodRecord; import com.oracle.svm.core.bootstrap.BootstrapMethodInfo; @@ -178,15 +178,21 @@ protected void run(StructuredGraph graph) { public abstract static class SharedBytecodeParser extends BytecodeParser { - private static final Class SCOPED_SUBSTRATE_ANNOTATION; private static final Executable SESSION_EXCEPTION_HANDLER_METHOD; private static final Class MAPPED_MEMORY_UTILS_PROXY_CLASS; private static final Class ABSTRACT_MEMORY_SEGMENT_IMPL_CLASS; static { - SCOPED_SUBSTRATE_ANNOTATION = ReflectionUtil.lookupClass("com.oracle.svm.core.foreign.SVMScoped"); - Class substrateForeignUtilClass = ReflectionUtil.lookupClass("com.oracle.svm.core.foreign.SubstrateForeignUtil"); - SESSION_EXCEPTION_HANDLER_METHOD = ReflectionUtil.lookupMethod(substrateForeignUtilClass, "sessionExceptionHandler", MemorySessionImpl.class, Object.class, long.class); + /* + * Class 'SubstrateForeignUtil' is optional because it is contained in a different + * distribution which may not always be available. + */ + Class substrateForeignUtilClass = ReflectionUtil.lookupClass(true, "com.oracle.svm.core.foreign.SubstrateForeignUtil"); + if (substrateForeignUtilClass != null) { + SESSION_EXCEPTION_HANDLER_METHOD = ReflectionUtil.lookupMethod(substrateForeignUtilClass, "sessionExceptionHandler", MemorySessionImpl.class, Object.class, long.class); + } else { + SESSION_EXCEPTION_HANDLER_METHOD = null; + } MAPPED_MEMORY_UTILS_PROXY_CLASS = ReflectionUtil.lookupClass("jdk.internal.access.foreign.MappedMemoryUtilsProxy"); ABSTRACT_MEMORY_SEGMENT_IMPL_CLASS = ReflectionUtil.lookupClass("jdk.internal.foreign.AbstractMemorySegmentImpl"); } @@ -247,9 +253,9 @@ protected void build(FixedWithNextNode startInstruction, FrameStateBuilder start } } - if (SCOPED_SUBSTRATE_ANNOTATION != null && SharedArenaSupport.SCOPED_ANNOTATION != null && graph.method() != null) { + if (graph.method() != null) { try { - if (AnnotationAccess.isAnnotationPresent(method, (Class) SCOPED_SUBSTRATE_ANNOTATION) && SharedArenaSupport.isAvailable()) { + if (AnnotationAccess.isAnnotationPresent(method, ForeignSupport.Scoped.class) && SharedArenaSupport.isAvailable()) { // substituted, only add the scoped node introduceScopeNodes(); } else if (AnnotationAccess.isAnnotationPresent(method, SharedArenaSupport.SCOPED_ANNOTATION) && SharedArenaSupport.isAvailable()) {