-
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
[Breaking Change Request] [vm/ffi] Disallow invoking ffi methods with generics #44621
Comments
https://dart-review.googlesource.com/c/sdk/+/177705/8/sdk/lib/ffi/allocation.dart#24 @lrhn suggested using an extension method instead of a top level method for // Before breaking change.
final pointer = allocate<Int8>(count: 10);
free(pointer);
// After breaking change with extension method `alloc` (`allocate` conflicts with instance method).
final pointer = malloc.alloc<Int8>(10);
malloc.free(pointer);
// After breaking change with extension method `call`.
final pointer = malloc<Int8>(10);
malloc.free(pointer); The final pointer = pool<Int8>(10);
pool.freeAll();
final pointer = bumpAllocator<Int8>(10);
bumpAllocator.free(pointer); We have 3 options:
Any preferences? |
@dcharkes Please make an announcement to https://groups.google.com/a/dartlang.org/g/announce cc @Hixie @matanlurey @vsmenon for review and approval. |
I have no opinion on this and thus no objection. I would encourage this change to be amply documented, in particular with the error message someone would see included in the documentation so that if they google for it they will find it. |
lgtm fyi - @leafpetersen - if we expect more general use for compile-time known type params. |
I don't work in this area, no comment. |
Announcement sent: https://groups.google.com/a/dartlang.org/g/announce/c/kZOGrc6-rIg |
Approved |
Introduces the Allocator API in `dart:ffi`. This CL does not yet roll `package:ffi` to use `Allocator`, because that breaks the checked in Dart in Fluter in g3. Instead, this coppies `_MallocAllocator` from `package:ffi` into the ffi tests for testing. This CL does not yet migrate off `allocate` and `free` in the SDK. That is done in a dependent CL. Issue: #44621 Issue: #38721 TEST=tests/ffi/allocator_test.dart TEST=tests/ffi/calloc_test.dart TEST=tests/ffi/vmspecific_static_checks_test.dart Change-Id: I173e213a750b8b3f594bb8d4fc72575f2b6b91f7 Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,analyzer-nnbd-linux-release-try,front-end-linux-release-x64-try,front-end-nnbd-linux-release-x64-try,benchmark-linux-try,dart-sdk-linux-try,pkg-linux-release-try,vm-ffi-android-release-arm-try,vm-ffi-android-release-arm64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-win-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/177705 Reviewed-by: Clement Skau <cskau@google.com>
New API landed in: https://dart-review.googlesource.com/c/sdk/+/177705 Issue: #44621 Issue: #38721 Change-Id: Id45274313edbb3842438b66b9c0917a86884c8ed Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178993 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
This CL does not yet roll `package:ffi` to use `Allocator`, because that breaks the checked in Dart in Flutter in g3. Instead, this uses the copy of `_CallocAllocator` from `package:ffi` in `calloc.dart` in tests/ffi. New API landed in: https://dart-review.googlesource.com/c/sdk/+/177705 Issue: #44621 Issue: #38721 Change-Id: Iedfc4a11d4606915a324c824372bca643016f5a3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178994 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
This CL does not yet roll `package:ffi` to use `Allocator`, because that breaks the checked in Dart in Flutter in g3. Instead, this copies `_CallocAllocator` from `package:ffi` into the benchmarks. (We need a copy per benchmark such that file-copying before running benchmarks works properly.) The copies can be deleted when we can update `package:ffi` in the DEPS file to contain `_CallocAllocator`. New API landed in: https://dart-review.googlesource.com/c/sdk/+/177705 Issue: #44621 Issue: #38721 Change-Id: I546de7ec65ceb6f05644a5f269b83f64656892e5 Cq-Include-Trybots: luci.dart.try:benchmark-linux-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178995 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
This CL does not yet roll `package:ffi` to use `Allocator`, because that breaks the checked in Dart in Flutter in g3. Instead, this uses the copy of `_CallocAllocator` from `package:ffi` in `calloc.dart`. New API landed in: https://dart-review.googlesource.com/c/sdk/+/177705 Issue: #44621 Issue: #38721 Change-Id: I10e53a363cd87c4c11e7042989e6957b82ae2a09 Cq-Include-Trybots: luci.dart.try:vm-kernel-win-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-mac-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178992 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
This CL does not yet roll `package:ffi` to use `Allocator`, because that breaks the checked in Dart in Flutter in g3. Instead, this copies `_CallocAllocator` from `package:ffi` into the samples. New API landed in: https://dart-review.googlesource.com/c/sdk/+/177705 Issue: #44621 Issue: #38721 Change-Id: I83da349c2e52d7f079aa1569b4726318fee24c9d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/177706 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
This can only be landed when `Allocator` and `Opaque` have rolled into Flutter/engine, that into Flutter/flutter, and that into g3. flutter/flutter/commit/a706cd211240f27be3b61f06d70f958c7a4156fe Deletes all the copies of `_CallocAllocator` and uses the one from `package:ffi` instead. Issue: #44622 Issue: #43974 Issue: #44621 Issue: #38721 Change-Id: I50b3b4c31a2b839b35e3e057bd54f463b90bc55e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179540 Reviewed-by: Aske Simon Christensen <askesc@google.com>
Issue: #44621 Issue: #44622 Change-Id: I9689db63a5b47946b501fac9df63cc86811d6e41 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179764 Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Changes `Utf8` and `Utf16` to extend `Opaque` instead of `Struct`. This means `.ref` is no longer available and `Pointer<Utf(..)>` should be used. See [breaking change #44622](dart-lang/sdk#44622) for more info. Removes `allocate` and `free`. Instead, introduces `calloc` which implements the new `Allocator` interface. See [breaking change #44621](dart-lang/sdk#44621) for more info. This pre-release requires Dart `2.12.0-265.0.dev` or greater.
This rewrites `sizeOf` calls in the CFE to skip the runtime entry when the type argument is constant. The runtime entry is still used when the type argument is generic. Forcing the type argument to be constant and removing the runtime entry will be done in follow up CLs. Bug: #44621 Bug: #38721 TEST=tests/ffi/sizeof_test.dart Change-Id: I17d14432e6ab22810729be6b5c2939a033d382c5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182262 Reviewed-by: Clement Skau <cskau@google.com>
This rewrites `elementAt` calls in the CFE to skip the runtime entry for `sizeOf` when the type argument is constant. The runtime entry is still used when the type argument is generic. Forcing the type argument to be constant and removing the runtime entry will be done in follow up CLs. Bug: #44621 Bug: #38721 TEST=tests/ffi/data_test.dart Change-Id: I480db43e7c115c24bd45f0ddab0cfea7eb8cfa58 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182263 Reviewed-by: Clement Skau <cskau@google.com>
This rewrites `Allocator.call` calls in the CFE to skip the runtime entry for `sizeOf` when the type argument is constant. The runtime entry is still used when the type argument is generic. Forcing the type argument to be constant and removing the runtime entry will be done in follow up CLs. Bug: #44621 Bug: #38721 TEST=test/ffi (almost all of them) Change-Id: I5e855fa2b63a5c1b7fa70dbaa1b89c122a82da6e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182264 Reviewed-by: Clement Skau <cskau@google.com>
This rewrites `Pointer<Struct>.ref` and `Pointer<Struct>[]` calls in the CFE to skip the runtime entry when the type argument is constant. The runtime entry is still used when the type argument is generic. Forcing the type argument to be constant and removing the runtime entry will be done in follow up CLs. Bug: #38721 Bug: #44621 Removing the runtime entry speeds up `.ref` significantly. before: FfiStruct.FieldLoadStore(RunTime): 18868.140186915887 us. after: FfiStruct.FieldLoadStore(RunTime): 270.5877976190476 us. Measurements from Linux x64 in JIT mode. Closes: #38648 TEST=tests/ffi/structs_test.dart Change-Id: I82abd930b5a9c5c78a8999c2bc49802d67d37534 Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-nnbd-linux-release-try,app-kernel-linux-debug-x64-try,dart-sdk-linux-try,front-end-nnbd-linux-release-x64-try,pkg-linux-debug-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182265 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Clement Skau <cskau@google.com>
This can only be landed when `Allocator`, `Opaque`, and `AllocatorAlloc` have rolled into Flutter/engine, that into Flutter/flutter, and into g3. Deletes all the copies of `_CallocAllocator` and uses the one from `package:ffi` instead. Bug: #44622 Bug: #43974 Bug: #44621 Bug: #38721 Change-Id: I486034b379b5a63cad4aefd503ccd0f2ce5dd45e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180188 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
I am honest - I am Dart nebiew and for my first little hobby project Currently I build complete native structs on the Dart side. It will possible to migrate this code according the new ffi changes?
|
Yes, just fire up the IDE with the latest beta release to get guidance from the analyzer hints. /// Helper class mapped to the C struct `
class NativeI2Cmsg extends Struct {
@Int16()
external int addr;
@Int16()
external int flags;
@Int16()
external int len;
external Pointer<Int8> buf;
}
Pointer<NativeI2Cmsg> _toNative(List<I2Cmsg> list) {
final ptr = calloc<NativeI2Cmsg>(list.length);
var index = 0;
for (var data in list) {
final msg = ptr.elementAt(index++);
msg.ref.addr = data.addr;
msg.ref.len = data.len;
var flags = 0;
if (data.flags.isNotEmpty) {
for (var f in data.flags) {
flags |= I2CmsgFlags2Int(f);
}
}
msg.ref.flags = flags;
msg.ref.buf = calloc<Int8>(data.len);
if (data.predefined.isNotEmpty) {
var count = 0;
for (var value in data.predefined) {
msg.ref.buf.elementAt(count++).value = value;
}
}
}
return ptr;
} |
Sorry @dcharkes its very late in the game to ask about this, but just to double check, now that this change has been made, allocating for generics as described in: https://stackoverflow.com/questions/68018694/type-safe-memory-allocation-with-dart-ffi is now not possible? |
@maks We already support that use case now with providing your own |
Update 2021-01-22: We will deprecate invoking the methods with generics in Dart 2.12 and remove support in 2.13.
Summary
Disallow invoking the following methods in
dart:ffi
with a generic and withPointer
with a generic type argument.sdk/sdk/lib/ffi/ffi.dart
Lines 24 to 27 in 897b1a2
sdk/sdk/lib/ffi/ffi.dart
Lines 63 to 64 in 897b1a2
sdk/sdk/lib/ffi/ffi.dart
Lines 535 to 547 in 897b1a2
And introduce the following to reduce boilerplate:
Motivation
This will enable us to do multiple things.
Struct
([vm/ffi] Support treeshaking of FFI structs #38721).Impact
package:ffi
'sallocate<T extends NativeType>()
will stop working.User code using
sizeOf
,.ref
, andelementAt
generically will stop working. However, at this moment we are not aware of any code written in such way. This breaking change request is to assess whether code such as that is out there.This requires changes API to take an
int
argument for the size or offset and let their callees invokesizeOf
with a non-generic type argument.Boilerplate reduction for allocation
Repeating the type argument is inconvenient. To address this we introduce the
Allocator
interface andcall
extension method onAllocator
todart:ffi
(see summary).Proposed changes: https://dart-review.googlesource.com/c/sdk/+/177705/10/sdk/lib/ffi/allocation.dart
Migration of package:ffi
We remove
allocate
frompackage:ffi
.We introduce
CallocAllocator
andCallocAllocator
which implement theAllocator
interface andconst
scalloc
andcalloc
.Proposed changes: dart-archive/ffi@b072465#diff-33eeafb9384f3239bb7f203cab73b7d099a5caa20a2033ef0a28b8019a57d647
Migration of users of package:ffi
Example migrations:
Discussion
Zero-initialize memory
We have two options for initializing memory to zero.
calloc
besidesmalloc
topackage:ffi
. This would use thecalloc
on all non-Windows OSes, andHEAP_ZERO_MEMORY
flag forHeapAlloc
on Windows. (This is the option that is prototyped.)bool zeroInitialize = false
toallocate
andAllocator.allocate
.In the first one, the implementor of the
Allocator
has control over whether something is zero-initialized. In the latter one, the caller ofallocate
has control over whether something is zero-initialized.Requires-constant-type-arguments
The need to disallow
.ref
onPointer<T extends Struct>
stems from the fact that Dart does not support callingnew T();
We could explore adding a pragma that would inline function bodies, or duplicate them with instantiated type arguments, as a more general solution to this problem.
When exploring this we should check what this kind of logic would to to code size.
Thanks to @mraleph for this suggestion.
The text was updated successfully, but these errors were encountered: