-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Build infrastructure to allow changing implementation of native calls to use FFI calls instead of runtime calls #43889
Comments
To clarify this a bit more, I think we want a solution where:
These are the properties our current natives have and we probably want to have the same properties for ffi natives as well. |
Some notes from offline discussions:
|
@mkustermann, @mraleph One approach (which I'm stealing from Daco) is to add something like One question I have though is whether we have the native function pointers at compile (IL -> asm.) time, or whether we need to do the lookup at runtime? |
I have not been deeply involved in the discussions - so I am not sure if there are any strong reasons to avoid native runtime entries to begin with, e.g. why not simply have: Pointer<Void> _resolve(String name) native "Ffi_resolve"; |
+1 To Slava's answer. It would be one mechanism to resolve any native function (1 <-> N relationship). We could later on, go one step further and make symbol resolution faster as well as avoid relying on natives (which we may want to replace entirely in the future) by "injecting" a C function pointer into a global dart field - the dart code could then call this C function directly via FFI (avoiding usage of natives): // Pointer to a `void* Lookup(Dart_Handle symbol_to_lookup)` function, which
// Dart code can call to resolve a native name.
@pragma('vm:entry-point')
Pointer<NativeFunction<Pointer<Void> Function(Dart_Handle)>> _resolver;
In JIT we could resolve the native function at compile time, though in AOT mode we cannot rely on this. |
Thank you for clarifying. My previous understanding was that natives (even for the resolve function) was off the table, so this was very helpful. I've put together a PoC in 170092, for a naive kernel transform into calls to a single native resolve function. Since the bottleneck is the native call to 'resolve' on every ffi native function call, we could amortise that away by caching the resulting function pointer, but I think doing so would likely require a static for every ffi native function. In the meantime I'll have a look at the ffi-based resolver. |
From off-thread follow-up: |
Implementing a cached |
Adds support for marking external functions as @FfiNative's, which will be called using fast FFI calls. Resolution happens by calling out to a new embedder provided Dart_FfiNativeResolver which the embedder can specify via Dart_SetFfiNativeResolver. TEST=vm/cc/DartAPI_FfiNativeResolver Bug: #43889 Change-Id: I3cfff360b05314499a81444b90f4ea0a1b937b0b Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170092 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This change essentially exposes `asFunction`'s `isLeaf` in `@FfiNative`, allowing us to declare FFI Natives as leaf calls. TEST=Adds tests/ffi/ffi_native_test.dart Bug: #43889 Change-Id: I2a396fae2ab28d21df282f3afb35fa401485ed52 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206375 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Clement Skau <cskau@google.com>
This makes it a compile-time error to add @FfiNative annotation to any non-static function, such as an instance method. TEST=tests/ffi/ffi_native_test.dart,pkg/analyzer/test/src/diagnostics/ffi_native_test.dart Bug: #43889 Change-Id: Ib9ec61345bb47e735ed635c5ceea15ab643f65a6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207306 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com>
Adds GetNativeField(o,i) to access NativeFieldWrapperClass{1-4} native fields directly in Dart instead of through VM API. This will allow us to pass `this` as a raw pointer instead of as a Dart handle which needs to be unwrapped. This will in turn allow ffi native calls for instance methods. TEST=Adds vm/cc/DartAPI_NativeFieldAccess Bug: #43889 Change-Id: I8006c735569fcbe5e49915a4c7e72c4ca85b356e Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/205482 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
Previously the synthetic field that holds the FfiNative function pointer was injected into the current library. This change makes sure we instead add the field to the relevant parent - Class or Library. TEST=Added regression test for name collision. Bug: #43889 Change-Id: Ifbf2d70de00e4748c179fe7d626c495675c2b338 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208502 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Clement Skau <cskau@google.com>
Adds a convenience function for working with FfiNatives where we often end up doing: class SomeClass extends NativeFieldWrapperClass1 { void doThing() => _doThing(Pointer.fromAddress(getNativeField(this))) @FfiNative<Void Function(Pointer)> external static void _doThing(Pointer self); } TEST=Existing. Bug: #43889 Change-Id: I983ba882574732b71b7ceafcb98b8ce5339e9003 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208503 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com>
This reverts commit 2e17bb2. Reason for revert: Breaks precomp. due to import of dart:ffi. Original change's description: > [VM] Adds getNativeFieldPtr(..) > > Adds a convenience function for working with FfiNatives > where we often end up doing: > > class SomeClass extends NativeFieldWrapperClass1 { > void doThing() => _doThing(Pointer.fromAddress(getNativeField(this))) > @FfiNative<Void Function(Pointer)> > external static void _doThing(Pointer self); > } > > TEST=Existing. > > Bug: #43889 > Change-Id: I983ba882574732b71b7ceafcb98b8ce5339e9003 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208503 > Commit-Queue: Clement Skau <cskau@google.com> > Reviewed-by: Tess Strickland <sstrickl@google.com> TBR=cskau@google.com,sstrickl@google.com Change-Id: I7bc9376f05664fda4fcf27b584081295195d5562 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: #43889 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209542 Reviewed-by: Clement Skau <cskau@google.com> Commit-Queue: Clement Skau <cskau@google.com>
Native methods in Dart are currently using our runtime call mechanism to call from Dart into C code. There is a significant performance overhead due to this: The native dart function cannot be inlined, we go indirectly through stubs, we box all arguments and make an array on the stack (in order to provide the C function a pointer to an array of arguments) ...
To avoid some of this overhead, we would like to enable calling natives using the existing FFI calling mechanism. That would allow us to pass unboxed primitives (e.g. integers/doubles) directly using C calling convention as well as dart objects via auto-wrapping in handles.
We want to prototype this on natives in Dart's core libraries and later make Flutter use it in
dart:ui
for faster calls into C (e.g. skia calls).This will require adding a symbol-lookup mechanism (either declaratively as we do with natives right now, or imperatively) to avoid depending on VM/Embedder symbols to be available at runtime.
Some tasks related to the Ffi Native support:
StackOverflow
checks in ffi trampoline (we don't do it for natives)/cc @mraleph
The text was updated successfully, but these errors were encountered: