Skip to content

Commit

Permalink
[ffi/docs] Elaborate on limitations on leaf functions
Browse files Browse the repository at this point in the history
CoreLibraryReviewExempt: VM-only API.
Closes: #53030
Change-Id: Ie62f66bcc9cbd631ad0e240bcc553be415e130bb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316589
Commit-Queue: Daco Harkes <[email protected]>
Reviewed-by: Slava Egorov <[email protected]>
Auto-Submit: Daco Harkes <[email protected]>
  • Loading branch information
dcharkes authored and Commit Queue committed Jul 31, 2023
1 parent eeff47f commit c9634d7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
17 changes: 13 additions & 4 deletions sdk/lib/ffi/dynamic_library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ extension DynamicLibraryExtension on DynamicLibrary {
///
/// [T] is the C function signature, and [F] is the Dart function signature.
///
/// [isLeaf] specifies whether the function is a leaf function.
/// A leaf function must not run Dart code or call back into the Dart VM.
/// Leaf calls are faster than non-leaf calls.
///
/// For example:
///
/// ```c
Expand All @@ -99,6 +95,19 @@ extension DynamicLibraryExtension on DynamicLibrary {
/// final add = dylib.lookupFunction<Int32 Function(Int32, Int32), int Function(int, int)>(
/// 'add');
/// ```
///
/// [isLeaf] specifies whether the function is a leaf function. Leaf functions
/// are small, short-running, non-blocking functions which are not allowed to
/// call back into Dart or use any Dart VM APIs. Leaf functions are invoked
/// bypassing some of the heavier parts of the standard Dart-to-Native calling
/// sequence which reduces the invocation overhead, making leaf calls faster
/// than non-leaf calls. However, this implies that a thread executing a leaf
/// function can't cooperate with the Dart runtime. A long running or blocking
/// leaf function will delay any operation which requires synchronization
/// between all threads associated with an isolate group until after the leaf
/// function returns. For example, if one isolate in a group is trying to
/// perform a GC and a second isolate is blocked in a leaf call, then the
/// first isolate will have to pause and wait until this leaf call returns.
external F lookupFunction<T extends Function, F extends Function>(
String symbolName,
{bool isLeaf = false});
Expand Down
52 changes: 40 additions & 12 deletions sdk/lib/ffi/ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,21 @@ final class _ArraySize<T extends NativeType> implements Array<T> {
/// Extension on [Pointer] specialized for the type argument [NativeFunction].
extension NativeFunctionPointer<NF extends Function>
on Pointer<NativeFunction<NF>> {
/// Convert to Dart function, automatically marshalling the arguments
/// and return value.
///
/// [isLeaf] specifies whether the function is a leaf function.
/// A leaf function must not run Dart code or call back into the Dart VM.
/// Leaf calls are faster than non-leaf calls.
/// Convert to Dart function, automatically marshalling the arguments and
/// return value.
///
/// [isLeaf] specifies whether the function is a leaf function. Leaf functions
/// are small, short-running, non-blocking functions which are not allowed to
/// call back into Dart or use any Dart VM APIs. Leaf functions are invoked
/// bypassing some of the heavier parts of the standard Dart-to-Native calling
/// sequence which reduces the invocation overhead, making leaf calls faster
/// than non-leaf calls. However, this implies that a thread executing a leaf
/// function can't cooperate with the Dart runtime. A long running or blocking
/// leaf function will delay any operation which requires synchronization
/// between all threads associated with an isolate group until after the leaf
/// function returns. For example, if one isolate in a group is trying to
/// perform a GC and a second isolate is blocked in a leaf call, then the
/// first isolate will have to pause and wait until this leaf call returns.
external DF asFunction<@DartRepresentationOf('NF') DF extends Function>(
{bool isLeaf = false});
}
Expand Down Expand Up @@ -1045,10 +1054,20 @@ abstract final class NativeApi {
final class FfiNative<T> {
final String nativeName;

/// Specifies whether the function is a leaf function.
/// Whether the function is a leaf function.
///
/// A leaf function must not run Dart code or call back into the Dart VM.
/// Leaf calls are faster than non-leaf calls.
/// Leaf functions are small, short-running, non-blocking functions which are
/// not allowed to call back into Dart or use any Dart VM APIs. Leaf functions
/// are invoked bypassing some of the heavier parts of the standard
/// Dart-to-Native calling sequence which reduces the invocation overhead,
/// making leaf calls faster than non-leaf calls. However, this implies that a
/// thread executing a leaf function can't cooperate with the Dart runtime. A
/// long running or blocking leaf function will delay any operation which
/// requires synchronization between all threads associated with an isolate
/// group until after the leaf function returns. For example, if one isolate
/// in a group is trying to perform a GC and a second isolate is blocked in a
/// leaf call, then the first isolate will have to pause and wait until this
/// leaf call returns.
final bool isLeaf;

const FfiNative(this.nativeName, {this.isLeaf = false});
Expand Down Expand Up @@ -1160,9 +1179,18 @@ final class Native<T> {

/// Whether the function is a leaf function.
///
/// A leaf function must not run Dart code or call back into the Dart VM.
///
/// Leaf calls are faster than non-leaf calls.
/// Leaf functions are small, short-running, non-blocking functions which are
/// not allowed to call back into Dart or use any Dart VM APIs. Leaf functions
/// are invoked bypassing some of the heavier parts of the standard
/// Dart-to-Native calling sequence which reduces the invocation overhead,
/// making leaf calls faster than non-leaf calls. However, this implies that a
/// thread executing a leaf function can't cooperate with the Dart runtime. A
/// long running or blocking leaf function will delay any operation which
/// requires synchronization between all threads associated with an isolate
/// group until after the leaf function returns. For example, if one isolate
/// in a group is trying to perform a GC and a second isolate is blocked in a
/// leaf call, then the first isolate will have to pause and wait until this
/// leaf call returns.
final bool isLeaf;

const Native({
Expand Down

0 comments on commit c9634d7

Please sign in to comment.