Skip to content
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 @@ -79,6 +79,7 @@
import jdk.internal.foreign.abi.CallingSequence;
import jdk.internal.foreign.abi.LinkerOptions;
import jdk.internal.foreign.abi.NativeEntryPoint;
import jdk.internal.foreign.abi.SharedUtils;
import jdk.internal.foreign.abi.VMStorage;
import jdk.internal.foreign.abi.aarch64.AArch64Architecture;
import jdk.internal.foreign.abi.x64.X86_64Architecture;
Expand Down Expand Up @@ -696,7 +697,6 @@ protected List<Adapter.Adaptation> generateAdaptations(NativeEntryPointInfo nep)

@Override
public void checkLibrarySupport() {
fail();
}

@Override
Expand All @@ -716,7 +716,7 @@ public int trampolineSize() {

@Override
public TrampolineTemplate generateTrampolineTemplate() {
return fail();
return null;
}
}

Expand Down Expand Up @@ -763,33 +763,7 @@ public AssignedLocation[] toMemoryAssignment(VMStorage[] argMoves, boolean forRe

@Override
public Map<String, MemoryLayout> canonicalLayouts() {
return Map.ofEntries(
// specified canonical layouts
Map.entry("bool", ValueLayout.JAVA_BOOLEAN),
Map.entry("char", ValueLayout.JAVA_BYTE),
Map.entry("short", ValueLayout.JAVA_SHORT),
Map.entry("int", ValueLayout.JAVA_INT),
Map.entry("float", ValueLayout.JAVA_FLOAT),
Map.entry("long", (ValueLayout) ValueLayout.JAVA_LONG),
Map.entry("long long", ValueLayout.JAVA_LONG),
Map.entry("double", ValueLayout.JAVA_DOUBLE),
Map.entry("void*", ValueLayout.ADDRESS),
Map.entry("size_t", (ValueLayout) ValueLayout.JAVA_LONG),
Map.entry("wchar_t", (ValueLayout) ValueLayout.JAVA_INT),
// unspecified size-dependent layouts
Map.entry("int8_t", ValueLayout.JAVA_BYTE),
Map.entry("int16_t", ValueLayout.JAVA_SHORT),
Map.entry("int32_t", ValueLayout.JAVA_INT),
Map.entry("int64_t", ValueLayout.JAVA_LONG),
// unspecified JNI layouts
Map.entry("jboolean", ValueLayout.JAVA_BOOLEAN),
Map.entry("jchar", ValueLayout.JAVA_CHAR),
Map.entry("jbyte", ValueLayout.JAVA_BYTE),
Map.entry("jshort", ValueLayout.JAVA_SHORT),
Map.entry("jint", ValueLayout.JAVA_INT),
Map.entry("jlong", ValueLayout.JAVA_LONG),
Map.entry("jfloat", ValueLayout.JAVA_FLOAT),
Map.entry("jdouble", ValueLayout.JAVA_DOUBLE));
return SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT);
}

@Override
Expand Down Expand Up @@ -937,36 +911,6 @@ public AssignedLocation[] toMemoryAssignment(VMStorage[] argMoves, boolean forRe
return storages;
}

protected static Map<String, MemoryLayout> canonicalLayouts(ValueLayout longLayout, ValueLayout sizetLayout, ValueLayout wchartLayout) {
return Map.ofEntries(
// specified canonical layouts
Map.entry("bool", ValueLayout.JAVA_BOOLEAN),
Map.entry("char", ValueLayout.JAVA_BYTE),
Map.entry("short", ValueLayout.JAVA_SHORT),
Map.entry("int", ValueLayout.JAVA_INT),
Map.entry("float", ValueLayout.JAVA_FLOAT),
Map.entry("long", longLayout),
Map.entry("long long", ValueLayout.JAVA_LONG),
Map.entry("double", ValueLayout.JAVA_DOUBLE),
Map.entry("void*", ValueLayout.ADDRESS),
Map.entry("size_t", sizetLayout),
Map.entry("wchar_t", wchartLayout),
// unspecified size-dependent layouts
Map.entry("int8_t", ValueLayout.JAVA_BYTE),
Map.entry("int16_t", ValueLayout.JAVA_SHORT),
Map.entry("int32_t", ValueLayout.JAVA_INT),
Map.entry("int64_t", ValueLayout.JAVA_LONG),
// unspecified JNI layouts
Map.entry("jboolean", ValueLayout.JAVA_BOOLEAN),
Map.entry("jchar", ValueLayout.JAVA_CHAR),
Map.entry("jbyte", ValueLayout.JAVA_BYTE),
Map.entry("jshort", ValueLayout.JAVA_SHORT),
Map.entry("jint", ValueLayout.JAVA_INT),
Map.entry("jlong", ValueLayout.JAVA_LONG),
Map.entry("jfloat", ValueLayout.JAVA_FLOAT),
Map.entry("jdouble", ValueLayout.JAVA_DOUBLE));
}

@Override
public Registers upcallSpecialArgumentsRegisters() {
return new Registers(AMD64.r10, AMD64.r11);
Expand Down Expand Up @@ -1058,7 +1002,7 @@ public void checkLibrarySupport() {

@Override
public Map<String, MemoryLayout> canonicalLayouts() {
return canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT);
return SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT);
}
}

Expand Down Expand Up @@ -1114,7 +1058,7 @@ public void checkLibrarySupport() {

@Override
public Map<String, MemoryLayout> canonicalLayouts() {
return canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR);
return SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 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
Expand Down Expand Up @@ -28,9 +28,31 @@

import com.oracle.svm.core.SubstrateOptions;

final class ForeignFunctionsEnabled implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return SubstrateOptions.ForeignAPISupport.getValue();
/**
* Set of predicates used to control activation of substitutions (depending on method
* {@link ForeignFunctionsRuntime#areFunctionCallsSupported()}) if FFM API support is enabled. In
* case of the FFM API support is disabled entirely, substitutions in
* {@link com.oracle.svm.core.jdk.ForeignDisabledSubstitutions} will be used.
*/
public final class ForeignAPIPredicates {
public static final class Enabled implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return SubstrateOptions.ForeignAPISupport.getValue();
}
}

public static final class FunctionCallsSupported implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return SubstrateOptions.ForeignAPISupport.getValue() && ForeignFunctionsRuntime.areFunctionCallsSupported();
}
}

public static final class FunctionCallsUnsupported implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return SubstrateOptions.ForeignAPISupport.getValue() && !ForeignFunctionsRuntime.areFunctionCallsSupported();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
import java.lang.constant.DirectMethodHandleDesc;
import java.lang.invoke.MethodHandle;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiConsumer;

import jdk.graal.compiler.word.Word;
import org.graalvm.collections.EconomicMap;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
Expand All @@ -44,6 +44,8 @@

import com.oracle.svm.core.FunctionPointerHolder;
import com.oracle.svm.core.OS;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.headers.WindowsAPIs;
Expand All @@ -53,6 +55,8 @@
import com.oracle.svm.core.util.VMError;

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

public class ForeignFunctionsRuntime {
Expand All @@ -76,6 +80,21 @@ public static ForeignFunctionsRuntime singleton() {
public ForeignFunctionsRuntime() {
}

public static boolean areFunctionCallsSupported() {
return switch (CABI.current()) {
case CABI.SYS_V -> !OS.DARWIN.isCurrent(); // GR-63074: code emit failures on
// darwin-amd64
case CABI.WIN_64, CABI.MAC_OS_AARCH_64, CABI.LINUX_AARCH_64 -> true;
default -> false;
};
}

public static RuntimeException functionCallsUnsupported() {
assert SubstrateOptions.ForeignAPISupport.getValue();
throw VMError.unsupportedFeature("Calling foreign functions is currently not supported on platform: " +
(OS.getCurrent().className + "-" + SubstrateUtil.getArchitectureName()).toLowerCase(Locale.ROOT));
}

@Platforms(Platform.HOSTED_ONLY.class)
public void addDowncallStubPointer(NativeEntryPointInfo nep, CFunctionPointer ptr) {
VMError.guarantee(!downcallStubs.containsKey(nep), "Seems like multiple stubs were generated for %s", nep);
Expand Down Expand Up @@ -117,6 +136,9 @@ CFunctionPointer getUpcallStubPointer(JavaEntryPointInfo jep) {
}

Pointer registerForUpcall(MethodHandle methodHandle, JavaEntryPointInfo jep) {
if (!areFunctionCallsSupported()) {
throw functionCallsUnsupported();
}
/*
* Look up the upcall stub pointer first to avoid unnecessary allocation and synchronization
* if it doesn't exist.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
Expand Down Expand Up @@ -67,7 +67,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", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "java.lang.foreign.SymbolLookup", onlyWith = ForeignAPIPredicates.Enabled.class)
public final class Target_java_lang_foreign_SymbolLookup {

@Substitute
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
Expand Down Expand Up @@ -35,7 +35,7 @@
* 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", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "jdk.internal.foreign.SystemLookup", onlyWith = ForeignAPIPredicates.Enabled.class)
public final class Target_jdk_internal_foreign_SystemLookup {
@Substitute
public Optional<MemorySegment> find(String name) {
Expand All @@ -48,6 +48,6 @@ public Optional<MemorySegment> find(String name) {
* 'jdk.internal.foreign.SystemLookup$WindowsFallbackSymbols') changes, ensure that the enum values
* are still in sync with 'com.oracle.svm.native.libchelper/src/syslookup.c'.
*/
@TargetClass(className = "jdk.internal.foreign.SystemLookup", innerClass = "WindowsFallbackSymbols", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "jdk.internal.foreign.SystemLookup", innerClass = "WindowsFallbackSymbols", onlyWith = ForeignAPIPredicates.Enabled.class)
final class Target_jdk_internal_foreign_SystemLookup_WindowsFallbackSymbols {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 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
Expand All @@ -24,7 +24,6 @@
*/
package com.oracle.svm.core.foreign;

import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.hosted.FieldValueTransformer;

import com.oracle.svm.core.annotate.Alias;
Expand All @@ -35,17 +34,18 @@
import com.oracle.svm.core.jdk.JDKLatest;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.foreign.Utils;
import jdk.vm.ci.meta.JavaKind;

@TargetClass(className = "jdk.internal.foreign.Utils", innerClass = "BaseAndScale", onlyWith = {ForeignFunctionsEnabled.class, JDKLatest.class})
@TargetClass(className = "jdk.internal.foreign.Utils", innerClass = "BaseAndScale", onlyWith = {ForeignAPIPredicates.Enabled.class, JDKLatest.class})
final class Target_jdk_internal_foreign_Utils_BaseAndScale {
@Alias //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = BaseFieldRecomputer.class) //
long base;
}

@TargetClass(className = "jdk.internal.foreign.Utils", innerClass = "BaseAndScale", onlyWith = {ForeignFunctionsEnabled.class, JDK21OrEarlier.class})
@TargetClass(className = "jdk.internal.foreign.Utils", innerClass = "BaseAndScale", onlyWith = {ForeignAPIPredicates.Enabled.class, JDK21OrEarlier.class})
final class Target_jdk_internal_foreign_Utils_BaseAndScale_JDK21 {
@Alias //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = BaseFieldRecomputer.class) //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;

@TargetClass(AbstractLinker.class)
@TargetClass(value = AbstractLinker.class, onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
public final class Target_jdk_internal_foreign_abi_AbstractLinker {
// Checkstyle: stop
@Alias //
Expand All @@ -59,7 +59,7 @@ public final class Target_jdk_internal_foreign_abi_AbstractLinker {
// Checkstyle: resume
}

@TargetClass(className = "jdk.internal.foreign.abi.SoftReferenceCache")
@TargetClass(className = "jdk.internal.foreign.abi.SoftReferenceCache", onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_SoftReferenceCache {
}

Expand Down Expand Up @@ -92,7 +92,7 @@ public MemorySegment makeStub(MethodHandle target, Arena arena) {
}
}

@TargetClass(value = SysVx64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(value = SysVx64Linker.class, onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_x64_sysv_SysVx64Linker {

@Substitute
Expand All @@ -101,7 +101,7 @@ UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor functi
}
}

@TargetClass(value = Windowsx64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(value = Windowsx64Linker.class, onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_x64_windows_Windowsx64Linker {

@Substitute
Expand All @@ -110,7 +110,7 @@ UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor functi
}
}

@TargetClass(value = MacOsAArch64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(value = MacOsAArch64Linker.class, onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_aarch64_macos_MacOsAArch64Linker {

@Substitute
Expand All @@ -119,7 +119,7 @@ UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor functi
}
}

@TargetClass(value = LinuxAArch64Linker.class, onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(value = LinuxAArch64Linker.class, onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_aarch64_linux_LinuxAArch64Linker {

@Substitute
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
Expand Down Expand Up @@ -38,7 +38,7 @@
* Packs the address of a {@link com.oracle.svm.hosted.foreign.DowncallStub} with some extra
* information.
*/
@TargetClass(className = "jdk.internal.foreign.abi.NativeEntryPoint", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "jdk.internal.foreign.abi.NativeEntryPoint", onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
@Substitute
public final class Target_jdk_internal_foreign_abi_NativeEntryPoint {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 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
Expand Down Expand Up @@ -33,7 +33,7 @@
import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.VMStorage;

@TargetClass(className = "jdk.internal.foreign.abi.UpcallLinker", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "jdk.internal.foreign.abi.UpcallLinker", onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_UpcallLinker {

@Substitute
Expand All @@ -48,7 +48,7 @@ private static void registerNatives() {
}
}

@TargetClass(className = "jdk.internal.foreign.abi.UpcallLinker", innerClass = "CallRegs", onlyWith = ForeignFunctionsEnabled.class)
@TargetClass(className = "jdk.internal.foreign.abi.UpcallLinker", innerClass = "CallRegs", onlyWith = ForeignAPIPredicates.FunctionCallsSupported.class)
final class Target_jdk_internal_foreign_abi_UpcallLinker_CallRegs {
@Alias private VMStorage[] argRegs;
@Alias private VMStorage[] retRegs;
Expand Down
Loading
Loading