mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 13:57:58 +00:00
Revert "[vm/ffi] Roll package:ffi
to Allocator
and Opaque
"
Revert submission 177862 Reason for revert: breaks g3 without https://github.com/flutter/engine/pull/23808 Reverted Changes: I50b3b4c31:[vm/ffi] Roll `package:ffi` to `Allocator` and `Op... I3f5b08c08:[vm/ffi] Change `Pointer<T extends Struct>.ref` to... I6141c193b:[vm/ffi] Disallow empty structs Change-Id: I128e7b096faea650e0ba0850a411eed3e97c00e6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180185 Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
parent
1fe4597638
commit
3cfcc5a8e5
4
DEPS
4
DEPS
|
@ -102,7 +102,7 @@ vars = {
|
||||||
|
|
||||||
"chromedriver_tag": "83.0.4103.39",
|
"chromedriver_tag": "83.0.4103.39",
|
||||||
"dartdoc_rev" : "9e61a4f11091aaa8998525a2692b14148dc24ab5",
|
"dartdoc_rev" : "9e61a4f11091aaa8998525a2692b14148dc24ab5",
|
||||||
"ffi_rev": "ad6700de10ca3af16f0c3d9ff8aa15d2bd7cd21c",
|
"ffi_rev": "31352979f261f7c6ea88fa0a2cfb0fdd004c38fb",
|
||||||
"fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
|
"fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
|
||||||
"file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
|
"file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
|
||||||
"glob_rev": "7c0ef8d4fa086f6b185c4dd724b700e7d7ad8f79",
|
"glob_rev": "7c0ef8d4fa086f6b185c4dd724b700e7d7ad8f79",
|
||||||
|
@ -115,7 +115,7 @@ vars = {
|
||||||
"http_throttle_tag" : "1.0.2",
|
"http_throttle_tag" : "1.0.2",
|
||||||
"icu_rev" : "79326efe26e5440f530963704c3c0ff965b3a4ac",
|
"icu_rev" : "79326efe26e5440f530963704c3c0ff965b3a4ac",
|
||||||
"idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
|
"idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
|
||||||
"intl_tag": "ade5a936a1de62e7cd04c3ea956c02bd491d7868",
|
"intl_tag": "0.17.0-nullsafety",
|
||||||
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
|
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
|
||||||
"json_rpc_2_rev": "b8dfe403fd8528fd14399dee3a6527b55802dd4d",
|
"json_rpc_2_rev": "b8dfe403fd8528fd14399dee3a6527b55802dd4d",
|
||||||
"linter_tag": "0.1.128",
|
"linter_tag": "0.1.128",
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:typed_data';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'digest.dart';
|
import 'digest.dart';
|
||||||
import 'types.dart';
|
import 'types.dart';
|
||||||
|
|
||||||
|
|
109
benchmarks/FfiBoringssl/dart/calloc.dart
Normal file
109
benchmarks/FfiBoringssl/dart/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -13,6 +13,7 @@ import 'dart:typed_data';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'digest.dart';
|
import 'digest.dart';
|
||||||
import 'types.dart';
|
import 'types.dart';
|
||||||
|
|
||||||
|
|
111
benchmarks/FfiBoringssl/dart2/calloc.dart
Normal file
111
benchmarks/FfiBoringssl/dart2/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -13,6 +13,7 @@ import 'dart:io';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dlopen_helper.dart';
|
import 'dlopen_helper.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
109
benchmarks/FfiCall/dart/calloc.dart
Normal file
109
benchmarks/FfiCall/dart/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -15,6 +15,7 @@ import 'dart:io';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dlopen_helper.dart';
|
import 'dlopen_helper.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
111
benchmarks/FfiCall/dart2/calloc.dart
Normal file
111
benchmarks/FfiCall/dart2/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -14,6 +14,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pointer store.
|
// Pointer store.
|
||||||
//
|
//
|
||||||
|
|
109
benchmarks/FfiMemory/dart/calloc.dart
Normal file
109
benchmarks/FfiMemory/dart/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -16,6 +16,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pointer store.
|
// Pointer store.
|
||||||
//
|
//
|
||||||
|
|
111
benchmarks/FfiMemory/dart2/calloc.dart
Normal file
111
benchmarks/FfiMemory/dart2/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -12,6 +12,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Struct field store (plus Pointer elementAt and load).
|
// Struct field store (plus Pointer elementAt and load).
|
||||||
//
|
//
|
||||||
|
|
109
benchmarks/FfiStruct/dart/calloc.dart
Normal file
109
benchmarks/FfiStruct/dart/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -14,6 +14,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Struct field store (plus Pointer elementAt and load).
|
// Struct field store (plus Pointer elementAt and load).
|
||||||
//
|
//
|
||||||
|
|
111
benchmarks/FfiStruct/dart2/calloc.dart
Normal file
111
benchmarks/FfiStruct/dart2/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -14,6 +14,7 @@ import 'dart:isolate';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../../tests/ffi/calloc.dart';
|
||||||
import '../../../../../tests/ffi/dylib_utils.dart';
|
import '../../../../../tests/ffi/dylib_utils.dart';
|
||||||
|
|
||||||
final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
|
final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
|
||||||
|
|
|
@ -11,6 +11,8 @@ import 'dart:ffi';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../tests/ffi/calloc.dart';
|
||||||
|
|
||||||
class X {
|
class X {
|
||||||
int field;
|
int field;
|
||||||
X(this.field);
|
X(this.field);
|
||||||
|
|
|
@ -10,6 +10,8 @@ import 'dart:io';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../tests/ffi/calloc.dart';
|
||||||
|
|
||||||
// pthread_t pthread_self()
|
// pthread_t pthread_self()
|
||||||
typedef PthreadSelfFT = int Function();
|
typedef PthreadSelfFT = int Function();
|
||||||
typedef PthreadSelfNFT = IntPtr Function();
|
typedef PthreadSelfNFT = IntPtr Function();
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'dart:isolate';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../../tests/ffi/calloc.dart';
|
||||||
import '../../../../../tests/ffi/dylib_utils.dart';
|
import '../../../../../tests/ffi/dylib_utils.dart';
|
||||||
|
|
||||||
final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
|
final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
|
||||||
|
|
|
@ -11,6 +11,8 @@ import 'dart:ffi';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../tests/ffi/calloc.dart';
|
||||||
|
|
||||||
class X {
|
class X {
|
||||||
int field;
|
int field;
|
||||||
X(this.field);
|
X(this.field);
|
||||||
|
|
|
@ -10,6 +10,8 @@ import 'dart:io';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../../../../tests/ffi/calloc.dart';
|
||||||
|
|
||||||
// pthread_t pthread_self()
|
// pthread_t pthread_self()
|
||||||
typedef PthreadSelfFT = int Function();
|
typedef PthreadSelfFT = int Function();
|
||||||
typedef PthreadSelfNFT = IntPtr Function();
|
typedef PthreadSelfNFT = IntPtr Function();
|
||||||
|
|
109
samples/ffi/calloc.dart
Normal file
109
samples/ffi/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -9,6 +9,8 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../calloc.dart';
|
||||||
|
|
||||||
/// An [Allocator] which frees all allocations at the same time.
|
/// An [Allocator] which frees all allocations at the same time.
|
||||||
///
|
///
|
||||||
/// The pool allows you to allocate heap memory, but ignores calls to [free].
|
/// The pool allows you to allocate heap memory, but ignores calls to [free].
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
import 'utf8_helpers.dart';
|
import 'utf8_helpers.dart';
|
||||||
|
import '../calloc.dart';
|
||||||
import '../dylib_utils.dart';
|
import '../dylib_utils.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
/// typedef struct {
|
/// typedef struct {
|
||||||
/// unsigned int bold : 1;
|
/// unsigned int bold : 1;
|
||||||
/// unsigned int underline : 2;
|
/// unsigned int underline : 2;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
print('start main');
|
print('start main');
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
typedef NativeUnaryOp = Int32 Function(Int32);
|
typedef NativeUnaryOp = Int32 Function(Int32);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
|
@ -8,3 +8,5 @@
|
||||||
library sqlite;
|
library sqlite;
|
||||||
|
|
||||||
export "src/database.dart";
|
export "src/database.dart";
|
||||||
|
|
||||||
|
export "src/ffi/calloc.dart" show calloc;
|
||||||
|
|
|
@ -15,6 +15,8 @@ import "bindings/types.dart" hide Database;
|
||||||
import "bindings/constants.dart";
|
import "bindings/constants.dart";
|
||||||
import "collections/closable_iterator.dart";
|
import "collections/closable_iterator.dart";
|
||||||
|
|
||||||
|
import 'ffi/calloc.dart';
|
||||||
|
|
||||||
/// [Database] represents an open connection to a SQLite database.
|
/// [Database] represents an open connection to a SQLite database.
|
||||||
///
|
///
|
||||||
/// All functions against a database may throw [SQLiteError].
|
/// All functions against a database may throw [SQLiteError].
|
||||||
|
|
|
@ -7,6 +7,8 @@ import "dart:ffi";
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
/// [Arena] manages allocated C memory.
|
/// [Arena] manages allocated C memory.
|
||||||
///
|
///
|
||||||
/// Arenas are zoned.
|
/// Arenas are zoned.
|
||||||
|
|
109
samples/ffi/sqlite/lib/src/ffi/calloc.dart
Normal file
109
samples/ffi/sqlite/lib/src/ffi/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
111
samples_2/ffi/calloc.dart
Normal file
111
samples_2/ffi/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -11,6 +11,8 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import '../calloc.dart';
|
||||||
|
|
||||||
/// An [Allocator] which frees all allocations at the same time.
|
/// An [Allocator] which frees all allocations at the same time.
|
||||||
///
|
///
|
||||||
/// The pool allows you to allocate heap memory, but ignores calls to [free].
|
/// The pool allows you to allocate heap memory, but ignores calls to [free].
|
||||||
|
|
|
@ -12,6 +12,7 @@ import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
import 'utf8_helpers.dart';
|
import 'utf8_helpers.dart';
|
||||||
|
import '../calloc.dart';
|
||||||
import '../dylib_utils.dart';
|
import '../dylib_utils.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
/// typedef struct {
|
/// typedef struct {
|
||||||
/// unsigned int bold : 1;
|
/// unsigned int bold : 1;
|
||||||
/// unsigned int underline : 2;
|
/// unsigned int underline : 2;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
print('start main');
|
print('start main');
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
typedef NativeUnaryOp = Int32 Function(Int32);
|
typedef NativeUnaryOp = Int32 Function(Int32);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
|
@ -10,3 +10,5 @@
|
||||||
library sqlite;
|
library sqlite;
|
||||||
|
|
||||||
export "src/database.dart";
|
export "src/database.dart";
|
||||||
|
|
||||||
|
export "src/ffi/calloc.dart" show calloc;
|
||||||
|
|
|
@ -17,6 +17,8 @@ import "bindings/types.dart" hide Database;
|
||||||
import "bindings/constants.dart";
|
import "bindings/constants.dart";
|
||||||
import "collections/closable_iterator.dart";
|
import "collections/closable_iterator.dart";
|
||||||
|
|
||||||
|
import 'ffi/calloc.dart';
|
||||||
|
|
||||||
/// [Database] represents an open connection to a SQLite database.
|
/// [Database] represents an open connection to a SQLite database.
|
||||||
///
|
///
|
||||||
/// All functions against a database may throw [SQLiteError].
|
/// All functions against a database may throw [SQLiteError].
|
||||||
|
|
|
@ -9,6 +9,8 @@ import "dart:ffi";
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
/// [Arena] manages allocated C memory.
|
/// [Arena] manages allocated C memory.
|
||||||
///
|
///
|
||||||
/// Arenas are zoned.
|
/// Arenas are zoned.
|
||||||
|
|
111
samples_2/ffi/sqlite/lib/src/ffi/calloc.dart
Normal file
111
samples_2/ffi/sqlite/lib/src/ffi/calloc.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
// @dart=2.9
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -13,6 +13,7 @@ import 'dart:ffi';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
109
tests/ffi/calloc.dart
Normal file
109
tests/ffi/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -5,8 +5,8 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import 'dart:ffi';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testPointerAllocateTooLarge();
|
testPointerAllocateTooLarge();
|
||||||
testPointerAllocateNegative();
|
testPointerAllocateNegative();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main(List<String> arguments) {
|
main(List<String> arguments) {
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
testStoreLoad();
|
testStoreLoad();
|
||||||
|
|
|
@ -9,6 +9,8 @@ import 'dart:typed_data';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
testInt8Load();
|
testInt8Load();
|
||||||
testInt8Store();
|
testInt8Store();
|
||||||
|
|
|
@ -16,6 +16,7 @@ import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
import 'callback_tests_utils.dart';
|
import 'callback_tests_utils.dart';
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'dylib_utils.dart';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'very_large_struct.dart';
|
import 'very_large_struct.dart';
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import 'dart:ffi';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -749,6 +749,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
@ -801,6 +802,7 @@ import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
import 'callback_tests_utils.dart';
|
import 'callback_tests_utils.dart';
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
|
@ -65,6 +65,8 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// ===== a.value = b ======
|
// ===== a.value = b ======
|
||||||
// The tests follow table cells left to right, top to bottom.
|
// The tests follow table cells left to right, top to bottom.
|
||||||
void store1() {
|
void store1() {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
final data = calloc<Uint8>(3);
|
final data = calloc<Uint8>(3);
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
class Struct43693 extends Struct {
|
class Struct43693 extends Struct {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate_nnbd_workaround.dart';
|
import 'coordinate_nnbd_workaround.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate_bare.dart' as bare;
|
import 'coordinate_bare.dart' as bare;
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
|
@ -15,6 +15,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
|
typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
|
||||||
|
|
|
@ -10,6 +10,8 @@ import 'dart:ffi'; //# 01: compile-time error
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart'; //# 01: compile-time error
|
import 'package:ffi/ffi.dart'; //# 01: compile-time error
|
||||||
|
|
||||||
|
import 'calloc.dart'; //# 01: compile-time error
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Pointer<Int8> p = //# 01: compile-time error
|
Pointer<Int8> p = //# 01: compile-time error
|
||||||
calloc(); //# 01: compile-time error
|
calloc(); //# 01: compile-time error
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import 'dart:ffi';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
109
tests/ffi_2/calloc.dart
Normal file
109
tests/ffi_2/calloc.dart
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
|
||||||
|
// rolled. We need to wait until the `Allocator` interface has rolled into
|
||||||
|
// Flutter.
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final DynamicLibrary stdlib = Platform.isWindows
|
||||||
|
? DynamicLibrary.open('kernel32.dll')
|
||||||
|
: DynamicLibrary.process();
|
||||||
|
|
||||||
|
typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
|
||||||
|
typedef PosixCalloc = Pointer Function(int num, int size);
|
||||||
|
final PosixCalloc posixCalloc =
|
||||||
|
stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
|
||||||
|
|
||||||
|
typedef PosixFreeNative = Void Function(Pointer);
|
||||||
|
typedef PosixFree = void Function(Pointer);
|
||||||
|
final PosixFree posixFree =
|
||||||
|
stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
|
||||||
|
|
||||||
|
typedef WinGetProcessHeapFn = Pointer Function();
|
||||||
|
final WinGetProcessHeapFn winGetProcessHeap = stdlib
|
||||||
|
.lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
|
||||||
|
final Pointer processHeap = winGetProcessHeap();
|
||||||
|
|
||||||
|
typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
|
||||||
|
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
|
||||||
|
final WinHeapAlloc winHeapAlloc =
|
||||||
|
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
|
||||||
|
|
||||||
|
typedef WinHeapFreeNative = Int32 Function(
|
||||||
|
Pointer heap, Uint32 flags, Pointer memory);
|
||||||
|
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
|
||||||
|
final WinHeapFree winHeapFree =
|
||||||
|
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
|
||||||
|
|
||||||
|
const int HEAP_ZERO_MEMORY = 8;
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
class _CallocAllocator implements Allocator {
|
||||||
|
const _CallocAllocator();
|
||||||
|
|
||||||
|
/// Allocates [byteCount] bytes of zero-initialized of memory on the native
|
||||||
|
/// heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` against the default public heap.
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the number of bytes or alignment cannot be
|
||||||
|
/// satisfied.
|
||||||
|
// TODO: Stop ignoring alignment if it's large, for example for SSE data.
|
||||||
|
@override
|
||||||
|
Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
|
||||||
|
Pointer<T> result;
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
|
||||||
|
.cast();
|
||||||
|
} else {
|
||||||
|
result = posixCalloc(byteCount, 1).cast();
|
||||||
|
}
|
||||||
|
if (result.address == 0) {
|
||||||
|
throw ArgumentError('Could not allocate $byteCount bytes.');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated on the native heap.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
|
||||||
|
/// against the default public heap. It may only be used against pointers
|
||||||
|
/// allocated in a manner equivalent to [allocate].
|
||||||
|
///
|
||||||
|
/// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
|
||||||
|
/// freed.
|
||||||
|
///
|
||||||
|
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
|
||||||
|
// of testing the return integer to be non-zero.
|
||||||
|
@override
|
||||||
|
void free(Pointer pointer) {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
|
||||||
|
throw ArgumentError('Could not free $pointer.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
posixFree(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages memory on the native heap.
|
||||||
|
///
|
||||||
|
/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
|
||||||
|
/// memory allocation.
|
||||||
|
///
|
||||||
|
/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
|
||||||
|
/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
|
||||||
|
/// public heap.
|
||||||
|
const Allocator calloc = _CallocAllocator();
|
|
@ -5,8 +5,8 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import 'dart:ffi';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testPointerAllocateTooLarge();
|
testPointerAllocateTooLarge();
|
||||||
testPointerAllocateNegative();
|
testPointerAllocateNegative();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main(List<String> arguments) {
|
main(List<String> arguments) {
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
testStoreLoad();
|
testStoreLoad();
|
||||||
|
|
|
@ -9,6 +9,8 @@ import 'dart:typed_data';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
testInt8Load();
|
testInt8Load();
|
||||||
testInt8Store();
|
testInt8Store();
|
||||||
|
|
|
@ -16,6 +16,7 @@ import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
import 'callback_tests_utils.dart';
|
import 'callback_tests_utils.dart';
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
|
|
@ -12,6 +12,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
import 'very_large_struct.dart';
|
import 'very_large_struct.dart';
|
||||||
|
|
|
@ -19,6 +19,7 @@ import "package:ffi/ffi.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
|
|
@ -749,6 +749,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
@ -801,6 +802,7 @@ import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
import 'callback_tests_utils.dart';
|
import 'callback_tests_utils.dart';
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// Reuse the struct classes.
|
// Reuse the struct classes.
|
||||||
import 'function_structs_by_value_generated_test.dart';
|
import 'function_structs_by_value_generated_test.dart';
|
||||||
|
|
|
@ -20,6 +20,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
// ===== a.value = b ======
|
// ===== a.value = b ======
|
||||||
// The tests follow table cells left to right, top to bottom.
|
// The tests follow table cells left to right, top to bottom.
|
||||||
void store1() {
|
void store1() {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
final data = calloc<Uint8>(3);
|
final data = calloc<Uint8>(3);
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
class Struct43693 extends Struct {
|
class Struct43693 extends Struct {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'coordinate_bare.dart' as bare;
|
import 'coordinate_bare.dart' as bare;
|
||||||
import 'coordinate.dart';
|
import 'coordinate.dart';
|
||||||
import 'ffi_test_helpers.dart';
|
import 'ffi_test_helpers.dart';
|
||||||
|
|
|
@ -15,6 +15,7 @@ import 'dart:ffi';
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
|
typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
|
||||||
|
|
|
@ -10,6 +10,8 @@ import 'dart:ffi'; //# 01: compile-time error
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart'; //# 01: compile-time error
|
import 'package:ffi/ffi.dart'; //# 01: compile-time error
|
||||||
|
|
||||||
|
import 'calloc.dart'; //# 01: compile-time error
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Pointer<Int8> p = //# 01: compile-time error
|
Pointer<Int8> p = //# 01: compile-time error
|
||||||
calloc(); //# 01: compile-time error
|
calloc(); //# 01: compile-time error
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
|
|
||||||
|
import 'calloc.dart';
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
Loading…
Reference in a new issue