Skip to content
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

[GR-49655] Option for experimental Foreign Function and Memory API support. #7980

Merged
merged 3 commits into from
Dec 11, 2023
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
3 changes: 3 additions & 0 deletions ci/common.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ local common_json = import "../common.json";
},

svm:: {
packages+: {
cmake: "==3.22.2",
},
environment+: {
DEFAULT_VM: "server",
LANG: "en_US.UTF-8",
Expand Down
5 changes: 3 additions & 2 deletions docs/reference-manual/native-image/ForeignInterface.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ permalink: /reference-manual/native-image/dynamic-features/foreign-interface/

# Foreign Function & Memory API in Native Image

The Foreign Function & Memory (FFM) API is a native interface that enables Java code to interact with native code and vice versa.
As of [JEP 442](https://openjdk.org/jeps/442){:target="_blank"}, it is a preview API of the Java platform and must be enabled with `--enable-preview`.
The Foreign Function & Memory (FFM) API is an interface that enables Java code to interact with native code and vice versa.
It has been finalized in JDK 22 with [JEP 454](https://openjdk.org/jeps/454){:target="_blank"}.
Support in Native Image is currently experimental and needs to be explicitly enabled with `-H:+ForeignAPISupport` (requiring `-H:+UnlockExperimentalVMOptions`).
Modules that are permitted to perform "restricted" native operations (including creating handles for calls to or from native code) must be specified using `--enable-native-access=`.
This page gives an overview of support for the FFM API in Native Image.

Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-45651) The Native Image agent now tracks calls to `ClassLoader.findSystemClass`, `ObjectInputStream.resolveClass` and `Bundles.of`, and registers resource bundles as bundle name-locale pairs.
* (GR-49807) Before this change the function `System#setSecurityManager` was always halting program execution with a VM error. This was inconvenient as the VM error prints an uncomprehensible error message and prevents further continuation of the program. For cases where the program is expected to throw an exception when `System#setSecurityManager` is called, execution on Native Image was not possible. Now, `System#setSecurityManager` throws an `java.lang.UnsupportedOperationException` by default. If the property `java.security.manager` is set to anything but `disallow` at program startup this function will throw a `java.lang.SecurityException` according to the Java spec.
* (GR-30433) Disallow the deprecated environment variable USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM=false.
* (GR-49655) Experimental support for parts of the [Foreign Function & Memory API](https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/ForeignInterface.md) (part of "Project Panama", [JEP 454](https://openjdk.org/jeps/454)) on AMD64. Must be enabled with `-H:+ForeignAPISupport` (requiring `-H:+UnlockExperimentalVMOptions`).

## GraalVM for JDK 21 (Internal Version 23.1.0)
* (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases.
Expand Down
18 changes: 1 addition & 17 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ def native_image_context_run(func, func_args=None, config=None, build_if_missing
'substratevm:OBJECTFILE',
'substratevm:POINTSTO',
'substratevm:NATIVE_IMAGE_BASE',
],
] + (['substratevm:SVM_FOREIGN'] if mx_sdk_vm.base_jdk().javaCompliance >= '22' else []),
support_distributions=['substratevm:SVM_GRAALVM_SUPPORT'],
stability="earlyadopter",
jlink=False,
Expand Down Expand Up @@ -1074,22 +1074,6 @@ def _native_image_launcher_extra_jvm_args():

additional_ni_dependencies = []

if mx.get_jdk(tag='default').javaCompliance >= '21':
mx_sdk_vm.register_graalvm_component(mx_sdk_vm.GraalVmJreComponent(
suite=suite,
name='SubstrateVM Foreign API Preview Feature',
short_name='svmforeign',
dir_name='svm-preview',
installable_id='native-image',
license_files=[],
third_party_license_files=[],
dependencies=['SubstrateVM'],
builder_jar_distributions=['substratevm:SVM_FOREIGN'],
installable=False,
jlink=False,
))
additional_ni_dependencies += ['svmforeign']

native_image = mx_sdk_vm.GraalVmJreComponent(
suite=suite,
name='Native Image',
Expand Down
12 changes: 4 additions & 8 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,11 @@
"jdk.internal.vm.ci" : [
],
},
"javaCompliance" : "21+",
"javaPreviewNeeded": "21+",
"javaCompliance" : "22+",
"annotationProcessors": [
"compiler:GRAAL_PROCESSOR",
"SVM_PROCESSOR",
],
"javac.lint.overrides": "-preview",
"checkstyle": "com.oracle.svm.hosted",
"workingSets": "SVM",
"jacoco" : "include",
Expand All @@ -719,13 +717,11 @@
"jdk.vm.ci.code"
],
},
"javaCompliance" : "21+",
"javaPreviewNeeded": "21+",
"javaCompliance" : "22+",
"annotationProcessors": [
"compiler:GRAAL_PROCESSOR",
"SVM_PROCESSOR",
],
"javac.lint.overrides": "-preview",
"checkstyle": "com.oracle.svm.hosted",
"workingSets": "SVM",
"jacoco" : "include",
Expand Down Expand Up @@ -2180,13 +2176,13 @@
"org.graalvm.nativeimage.builder"
],
"exports" : [
"* to org.graalvm.nativeimage.builder",
"* to org.graalvm.nativeimage.builder"
],
"requiresConcealed": {
"jdk.internal.vm.ci" : [
"jdk.vm.ci.meta",
"jdk.vm.ci.code",
"jdk.vm.ci.amd64",
"jdk.vm.ci.amd64",
],
"java.base": [
"jdk.internal.foreign",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@
import java.util.Objects;
import java.util.stream.Stream;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.calc.ReinterpretNode;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand All @@ -53,6 +50,9 @@
import com.oracle.svm.core.headers.WindowsAPIs;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.calc.ReinterpretNode;
import jdk.internal.foreign.CABI;
import jdk.internal.foreign.abi.Binding;
import jdk.internal.foreign.abi.CallingSequence;
Expand Down Expand Up @@ -534,7 +534,7 @@ protected List<Adapter.Adaptation> generateAdaptations(NativeEntryPointInfo nep)
@Platforms(Platform.HOSTED_ONLY.class)
public void checkLibrarySupport() {
String name = "SystemV (Linux AMD64)";
VMError.guarantee(LibC.isSupported(), "Foreign functions feature requires LibC support on " + name);
VMError.guarantee(LibC.isSupported(), "Foreign functions feature requires LibC support on %s", name);
}

@Override
Expand Down Expand Up @@ -587,8 +587,8 @@ protected List<Adapter.Adaptation> generateAdaptations(NativeEntryPointInfo nep)
@Platforms(Platform.HOSTED_ONLY.class)
public void checkLibrarySupport() {
String name = "Win64 (Windows AMD64)";
VMError.guarantee(LibC.isSupported(), "Foreign functions feature requires LibC support on" + name);
VMError.guarantee(WindowsAPIs.isSupported(), "Foreign functions feature requires Windows APIs support on" + name);
VMError.guarantee(LibC.isSupported(), "Foreign functions feature requires LibC support on %s", name);
VMError.guarantee(WindowsAPIs.isSupported(), "Foreign functions feature requires Windows APIs support on %s", name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.foreign;

import java.util.function.BooleanSupplier;

import com.oracle.svm.core.SubstrateOptions;

final class ForeignFunctionsEnabled implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return SubstrateOptions.ForeignAPISupport.getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.HAS_SIDE_EFFECT;

import org.graalvm.collections.EconomicMap;
import jdk.graal.compiler.api.replacements.Fold;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand All @@ -44,6 +43,7 @@
import com.oracle.svm.core.snippets.SubstrateForeignCallTarget;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.internal.foreign.abi.CapturableState;

public class ForeignFunctionsRuntime {
Expand All @@ -59,7 +59,7 @@ public ForeignFunctionsRuntime() {

@Platforms(Platform.HOSTED_ONLY.class)
public void addDowncallStubPointer(NativeEntryPointInfo nep, CFunctionPointer ptr) {
VMError.guarantee(!downcallStubs.containsKey(nep), "Seems like multiple stubs were generated for " + nep);
VMError.guarantee(!downcallStubs.containsKey(nep), "Seems like multiple stubs were generated for %s", nep);
VMError.guarantee(downcallStubs.put(nep, new FunctionPointerHolder(ptr)) == null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
* succeed. See
* {@link com.oracle.svm.core.jdk.Target_java_lang_ClassLoader#loadLibrary(java.lang.Class, java.lang.String)}
*/
@TargetClass(className = "java.lang.foreign.SymbolLookup")
@TargetClass(className = "java.lang.foreign.SymbolLookup", onlyWith = ForeignFunctionsEnabled.class)
public final class Target_java_lang_foreign_SymbolLookup {

@Substitute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
* libraries. The provided libraries are not really defined in the documentation, so the best we can
* do is load the exact same libraries as HotSpot.
*/
@TargetClass(className = "jdk.internal.foreign.SystemLookup")
@TargetClass(className = "jdk.internal.foreign.SystemLookup", onlyWith = ForeignFunctionsEnabled.class)
public final class Target_jdk_internal_foreign_SystemLookup {
@Substitute
public Optional<MemorySegment> find(String name) {
return RuntimeSystemLookup.INSTANCE.find(name);
}
}

@TargetClass(className = "jdk.internal.foreign.SystemLookup", innerClass = "WindowsFallbackSymbols")
@TargetClass(className = "jdk.internal.foreign.SystemLookup", innerClass = "WindowsFallbackSymbols", onlyWith = ForeignFunctionsEnabled.class)
@Delete
final class Target_jdk_internal_foreign_SystemLookup_WindowsFallbackSymbols {
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
* Packs the address of a {@link com.oracle.svm.hosted.foreign.DowncallStub} with some extra
* information.
*/
@TargetClass(className = "jdk.internal.foreign.abi.NativeEntryPoint")
@TargetClass(className = "jdk.internal.foreign.abi.NativeEntryPoint", onlyWith = ForeignFunctionsEnabled.class)
@Substitute
public final class Target_jdk_internal_foreign_abi_NativeEntryPoint {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
* <p>
* It seems like this could be easily supported once thread-local handshakes are supported.
*/
@TargetClass(className = "jdk.internal.misc.ScopedMemoryAccess")
@TargetClass(className = "jdk.internal.misc.ScopedMemoryAccess", onlyWith = ForeignFunctionsEnabled.class)
public final class Target_jdk_internal_misc_ScopedMemoryAccess {
@Substitute
static void registerNatives() {
Expand Down Expand Up @@ -80,6 +80,6 @@ boolean closeScope0(MemorySessionImpl session) {
}
}

@TargetClass(className = "jdk.internal.misc.ScopedMemoryAccess$ScopedAccessError", onlyWith = JDK22OrLater.class)
@TargetClass(className = "jdk.internal.misc.ScopedMemoryAccess$ScopedAccessError", onlyWith = {JDK22OrLater.class, ForeignFunctionsEnabled.class})
final class Target_jdk_internal_misc_ScopedMemoryAccess_ScopedAccessError {
}
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,9 @@ public enum ReportingMode {
@Option(help = "Include all classes, methods, fields, and resources from given paths", type = OptionType.Debug) //
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> IncludeAllFromPath = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());

@Option(help = "Support for calls via the Java Foreign Function and Memory API", type = Expert) //
public static final HostedOptionKey<Boolean> ForeignAPISupport = new HostedOptionKey<>(false);

public static class TruffleStableOptions {

@Option(help = "Automatically copy the necessary language resources to the resources/languages directory next to the produced image." +
Expand Down
Loading