mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 08:20:31 +00:00
4be2981c2d
Right each `Pointer.fromFunction()` invocation will lead to creation of a new ffi trampoline function & it's following JITed code. In AOT we have exactly one ffi trampoline per target/native-signature/exceptional-return combination. => This CL ensures we have only one such function. Furthermore each `Pointer.fromFunction()` will currently perform 2 runtime calls in JIT: One to create a `Function` object, the other to JIT that function & register callback metadata. => This CL ensures we won't do a runtime call to get a function, instead do it at compile-time (as in AOT) Furthermore we eagerly assign a callback-id to the unique/deduped ffi trampoline callbacks. Only when the application requests a pointer, do we populate metadata on the `Thread` object. This CL doesn't (yet) change the fact that in JIT mode we have isolate-specific jit trampolines (that will call now shared ffi trampoline functions). We also avoid baking in C++ runtime function pointers in generated code. As a result we can now preserve ffi trampolines across AppJIT serialization. As a nice side-effect, we remove 100 lines of code. TEST=ffi{,_2}/ffi_callback_unique_test Issue https://github.com/dart-lang/sdk/issues/50611 Change-Id: I458831a47b041a088086f28f825de2a3849f6adc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273420 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
138 lines
2.7 KiB
Dart
138 lines
2.7 KiB
Dart
// 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.
|
|
|
|
// @dart = 2.9
|
|
|
|
// SharedObjects=ffi_test_functions
|
|
|
|
import 'dart:ffi';
|
|
|
|
import 'package:expect/expect.dart';
|
|
import 'package:ffi/ffi.dart';
|
|
|
|
// We want at least 1 mapping to satisfy the static checks.
|
|
const notTestingOn = Abi.fuchsiaArm64;
|
|
|
|
@AbiSpecificIntegerMapping({
|
|
notTestingOn: Int8(),
|
|
})
|
|
class Incomplete extends AbiSpecificInteger {
|
|
const Incomplete();
|
|
}
|
|
|
|
void main() {
|
|
if (Abi.current() == notTestingOn) {
|
|
return;
|
|
}
|
|
testSizeOf();
|
|
testStoreLoad();
|
|
testStoreLoadIndexed();
|
|
testStruct();
|
|
testInlineArray();
|
|
testInlineArray2();
|
|
testAsFunction();
|
|
}
|
|
|
|
void testSizeOf() {
|
|
Expect.throws(() {
|
|
sizeOf<Incomplete>();
|
|
});
|
|
}
|
|
|
|
void testStoreLoad() {
|
|
final p = calloc<Int64>().cast<Incomplete>();
|
|
Expect.throws(() {
|
|
p.value = 10;
|
|
});
|
|
Expect.throws(() {
|
|
p.value;
|
|
});
|
|
calloc.free(p);
|
|
}
|
|
|
|
void testStoreLoadIndexed() {
|
|
final p = calloc<Int64>().cast<Incomplete>();
|
|
Expect.throws(() {
|
|
p[0] = 10;
|
|
});
|
|
Expect.throws(() {
|
|
p[1];
|
|
});
|
|
calloc.free(p);
|
|
}
|
|
|
|
class IncompleteStruct extends Struct {
|
|
@Incomplete()
|
|
int a0;
|
|
|
|
@Incomplete()
|
|
int a1;
|
|
}
|
|
|
|
void testStruct() {
|
|
final p = calloc<Int64>(2).cast<IncompleteStruct>();
|
|
Expect.throws(() {
|
|
p.ref.a0 = 1;
|
|
});
|
|
Expect.throws(() {
|
|
p.ref.a0;
|
|
});
|
|
calloc.free(p);
|
|
}
|
|
|
|
class IncompleteArrayStruct extends Struct {
|
|
@Array(100)
|
|
Array<Incomplete> a0;
|
|
}
|
|
|
|
void testInlineArray() {
|
|
final p = calloc<Int64>(100).cast<IncompleteArrayStruct>();
|
|
final array = p.ref.a0;
|
|
Expect.throws(() {
|
|
array[3] = 4;
|
|
});
|
|
Expect.throws(() {
|
|
array[3];
|
|
});
|
|
calloc.free(p);
|
|
}
|
|
|
|
const _dim1 = 8;
|
|
const _dim2 = 4;
|
|
|
|
class IncompleteArrayArrayStruct extends Struct {
|
|
@Array(_dim1, _dim2)
|
|
Array<Array<Incomplete>> a0;
|
|
}
|
|
|
|
void testInlineArray2() {
|
|
final p = calloc<Int64>(100).cast<IncompleteArrayArrayStruct>();
|
|
Expect.throws(() {
|
|
p.elementAt(3);
|
|
});
|
|
calloc.free(p);
|
|
}
|
|
|
|
void testAsFunction() {
|
|
Expect.throws(() {
|
|
nullptr
|
|
.cast<NativeFunction<Int32 Function(Incomplete)>>()
|
|
.asFunction<int Function(int)>();
|
|
});
|
|
Expect.throws(() {
|
|
nullptr
|
|
.cast<NativeFunction<Incomplete Function(Int32)>>()
|
|
.asFunction<int Function(int)>();
|
|
});
|
|
Expect.throws(() {
|
|
nullptr
|
|
.cast<NativeFunction<Int32 Function(IncompleteArrayStruct)>>()
|
|
.asFunction<int Function(IncompleteArrayStruct)>();
|
|
});
|
|
Expect.throws(() {
|
|
nullptr
|
|
.cast<NativeFunction<IncompleteArrayStruct Function()>>()
|
|
.asFunction<IncompleteArrayStruct Function()>();
|
|
});
|
|
}
|