Skip to content

[GR-65636] Make foreign API support optional in parser. #11355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -215,7 +214,3 @@ void closeScope0Unsupported(Target_jdk_internal_foreign_MemorySessionImpl sessio
throw SharedArenasDisabled.fail();
}
}

@Retention(RetentionPolicy.RUNTIME)
@interface SVMScoped {
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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 {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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<? extends Annotation>) 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()) {
Expand Down