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 @@ -28,7 +28,7 @@
"title": "Specifies if a call state should be captured. Which states to capture is determined at run time. See also: 'java.lang.foreign.Linker.Option.captureCallState'"
},
"critical": {
"type": ["boolean", "object"],
"type": "object",
"title": "see 'java.lang.foreign.Linker.Option.critical'",
"properties": {
"allowHeapAccess": {
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-53985) Add experimental option `ClassForNameRespectsClassLoader` that makes `Class.forName(...)` respect the class loader hierarchy.
* (GR-59869) Implemented initial optimization of Java Vector API (JEP 338) operations in native images. See the compiler changelog for more details.
* (GR-63268) Reflection and JNI queries do not require metadata entries to throw the expected JDK exception when querying a class that doesn't exist under `--exact-reachability-metadata` if the query cannot possibly be a valid class name
* (GR-60208) Adds the Tracing Agent support for applications using the Foreign Function & Memory (FFM) API. The agent generates FFM configuration in _foreign-config.json_. Additionally, support for FFM configurations has been added to the `native-image-configure` tool.
* (GR-47881) Remove the total number of loaded types, fields, and methods from the build output, deprecated these metrics in the build output schema, and removed already deprecated build output metrics.

## GraalVM for JDK 24 (Internal Version 24.2.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ private static void traceSerializeBreakpoint(JNIEnvironment env, String function
traceBreakpoint(env, "serialization", nullHandle(), nullHandle(), nullHandle(), function, result, stackTrace, args);
}

private static void traceForeignBreakpoint(JNIEnvironment env, String function, Object result, JNIMethodId[] stackTrace, Object... args) {
traceBreakpoint(env, "foreign", nullHandle(), nullHandle(), nullHandle(), function, result, stackTrace, args);
}

private static void traceBreakpoint(JNIEnvironment env, String context, JNIObjectHandle clazz, JNIObjectHandle declaringClass, JNIObjectHandle callerClass, String function, Object result,
JNIMethodId[] stackTrace, Object[] args) {
if (tracer != null) {
Expand Down Expand Up @@ -350,6 +354,54 @@ private static boolean handleGetField(JNIEnvironment jni, JNIObjectHandle thread
return true;
}

private static boolean downcallHandle0(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) {
JNIObjectHandle receiver = getReceiver(thread);
JNIObjectHandle function = getObjectArgument(thread, 1);
JNIObjectHandle options = getObjectArgument(thread, 2);

JNIObjectHandle result = Support.callObjectMethodLL(jni, receiver, bp.method, function, options);
boolean isValidResult = !clearException(jni) && nullHandle().notEqual(result);

String returnLayoutString = Tracer.UNKNOWN_VALUE;
Object argumentLayoutStrings = Tracer.UNKNOWN_VALUE;
Object optionsStrings = Tracer.UNKNOWN_VALUE;
if (isValidResult) {
NativeImageAgentJNIHandleSet handles = agent.handles();
returnLayoutString = ForeignUtil.getReturnLayoutString(jni, handles, function);
argumentLayoutStrings = ForeignUtil.getArgumentLayoutStrings(jni, handles, function);
optionsStrings = ForeignUtil.getOptionsStrings(jni, handles, options);
}

traceForeignBreakpoint(jni, bp.specification.methodName, isValidResult, state.getFullStackTraceOrNull(), returnLayoutString, argumentLayoutStrings, optionsStrings);
return true;
}

private static boolean upcallStub(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) {
JNIObjectHandle receiver = getReceiver(thread);
JNIObjectHandle target = getObjectArgument(thread, 1);
JNIObjectHandle function = getObjectArgument(thread, 2);
JNIObjectHandle arena = getObjectArgument(thread, 3);
JNIObjectHandle options = getObjectArgument(thread, 4);

JNIObjectHandle result = Support.callObjectMethodLLLL(jni, receiver, bp.method, target, function, arena, options);
boolean isValidResult = !clearException(jni) && nullHandle().notEqual(result);

String returnLayoutString = Tracer.UNKNOWN_VALUE;
Object argumentLayoutStrings = Tracer.UNKNOWN_VALUE;
Object optionsStrings = Tracer.UNKNOWN_VALUE;
Object targetString = Tracer.UNKNOWN_VALUE;
if (isValidResult) {
NativeImageAgentJNIHandleSet handles = agent.handles();
returnLayoutString = ForeignUtil.getReturnLayoutString(jni, handles, function);
argumentLayoutStrings = ForeignUtil.getArgumentLayoutStrings(jni, handles, function);
optionsStrings = ForeignUtil.getOptionsStrings(jni, handles, options);
targetString = ForeignUtil.getTargetString(jni, handles, target);
}

traceForeignBreakpoint(jni, bp.specification.methodName, isValidResult, state.getFullStackTraceOrNull(), returnLayoutString, argumentLayoutStrings, optionsStrings, targetString);
return true;
}

private static final CEntryPointLiteral<AllocateInstanceFunctionPointer> nativeAllocateInstance = CEntryPointLiteral.create(
BreakpointInterceptor.class, "nativeAllocateInstance", JNIEnvironment.class, JNIObjectHandle.class, JNIObjectHandle.class);

Expand Down Expand Up @@ -1713,7 +1765,15 @@ private interface BreakpointHandler {
optionalBrk("java/lang/Class", "getNestMembers", "()[Ljava/lang/Class;",
BreakpointInterceptor::getNestMembers),
optionalBrk("java/lang/Class", "getSigners", "()[Ljava/lang/Object;",
BreakpointInterceptor::getSigners)
BreakpointInterceptor::getSigners),

/* FFM API was introduced in Java 22 */
brk("jdk/internal/foreign/abi/AbstractLinker", "downcallHandle0",
"(Ljava/lang/foreign/FunctionDescriptor;[Ljava/lang/foreign/Linker$Option;)Ljava/lang/invoke/MethodHandle;",
BreakpointInterceptor::downcallHandle0),
brk("jdk/internal/foreign/abi/AbstractLinker", "upcallStub",
"(Ljava/lang/invoke/MethodHandle;Ljava/lang/foreign/FunctionDescriptor;Ljava/lang/foreign/Arena;[Ljava/lang/foreign/Linker$Option;)Ljava/lang/foreign/MemorySegment;",
BreakpointInterceptor::upcallStub)
};

private static boolean allocateInstance(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) {
Expand Down
Loading