dart-sdk/tests/ffi/function_callbacks_test.dart
Ryan Macnak 1a9acb9171 [vm, ffi] Make callbacks profiler-safe.
Delay changing Thread::vm_tag on callback entry and restore the tag early on callback return so that the profiler doesn't see the "running Dart" tag unless it can also see the fake return address marking the entry frame.

TEST=ffi/async_void_function_callbacks, ffi/function_callbacks_subtype, ffi/function_callbacks, ffi/isolate_local_function_callbacks
Bug: https://github.com/dart-lang/sdk/issues/52814
Change-Id: I40d80ec7c44063d078db0e211565e2d127c6b81e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/367460
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2024-05-28 21:16:41 +00:00

234 lines
6.4 KiB
Dart

// Copyright (c) 2019, 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 test program for testing dart:ffi function pointers with callbacks.
//
// VMOptions=
// VMOptions=--stacktrace-every=100
// VMOptions=--use-slow-path
// VMOptions=--use-slow-path --stacktrace-every=100
// VMOptions=--dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// VMOptions=--test_il_serialization
// VMOptions=--profiler --profile_vm=true
// VMOptions=--profiler --profile_vm=false
// SharedObjects=ffi_test_functions
import 'dart:ffi';
import 'callback_tests_utils.dart';
typedef SimpleAdditionType = Int32 Function(Int32, Int32);
int simpleAddition(int x, int y) {
print("simpleAddition($x, $y)");
return x + y;
}
class Foo {
static int simpleAddition(int x, int y) {
print("Foo.simpleAddition($x, $y)");
return x + y;
}
}
typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
int intComputation(int a, int b, int c, int d) {
print("intComputation($a, $b, $c, $d)");
return d - c + b - a;
}
typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
int uintComputation(int a, int b, int c, int d) {
print("uintComputation($a, $b, $c, $d)");
return d - c + b - a;
}
typedef SimpleMultiplyType = Double Function(Double);
double simpleMultiply(double x) {
print("simpleMultiply($x)");
return x * 1.337;
}
typedef SimpleMultiplyFloatType = Float Function(Float);
double simpleMultiplyFloat(double x) {
print("simpleMultiplyFloat($x)");
return x * 1.337;
}
typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
int manyInts(
int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
print("manyInts($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
return a + b + c + d + e + f + g + h + i + j;
}
typedef ManyDoublesType = Double Function(Double, Double, Double, Double,
Double, Double, Double, Double, Double, Double);
double manyDoubles(double a, double b, double c, double d, double e, double f,
double g, double h, double i, double j) {
print("manyDoubles($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
return a + b + c + d + e + f + g + h + i + j;
}
typedef ManyArgsType = Double Function(
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double);
double manyArgs(
int _1,
double _2,
int _3,
double _4,
int _5,
double _6,
int _7,
double _8,
int _9,
double _10,
int _11,
double _12,
int _13,
double _14,
int _15,
double _16,
int _17,
double _18,
int _19,
double _20) {
print("manyArgs( $_1, $_2, $_3, $_4, $_5, $_6, $_7, $_8, $_9, $_10," +
"$_11, $_12, $_13, $_14, $_15, $_16, $_17, $_18, $_19, $_20)");
return _1 +
_2 +
_3 +
_4 +
_5 +
_6 +
_7 +
_8 +
_9 +
_10 +
_11 +
_12 +
_13 +
_14 +
_15 +
_16 +
_17 +
_18 +
_19 +
_20;
}
typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..value = 1337;
typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr.elementAt(1);
typedef ReturnVoid = Void Function();
void returnVoid() {}
void throwException() {
throw "Exception.";
}
typedef ThrowExceptionInt = IntPtr Function();
int throwExceptionInt() {
throw "Exception.";
}
typedef ThrowExceptionDouble = Double Function();
double throwExceptionDouble() {
throw "Exception.";
}
typedef ThrowExceptionPointer = Pointer<Void> Function();
Pointer<Void> throwExceptionPointer() {
throw "Exception.";
}
typedef TakeMaxUint8x10Type = IntPtr Function(
Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8);
int takeMaxUint8x10(
int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
print("takeMaxUint8x10($a, $b, $c, $d, $e, $f, $g, $h, $i, $j)");
return a == 0xff &&
b == 0xff &&
c == 0xff &&
d == 0xff &&
e == 0xff &&
f == 0xff &&
g == 0xff &&
h == 0xff &&
i == 0xff &&
j == 0xff
? 1
: 0;
}
typedef ReturnMaxUint8Type = Uint8 Function();
int returnMaxUint8() {
return 0xff;
}
int returnMaxUint8v2() {
return 0xabcff;
}
final testcases = [
CallbackTest("SimpleAddition",
Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
CallbackTest("SimpleAddition",
Pointer.fromFunction<SimpleAdditionType>(Foo.simpleAddition, 0)),
CallbackTest("IntComputation",
Pointer.fromFunction<IntComputationType>(intComputation, 0)),
CallbackTest("UintComputation",
Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
CallbackTest("SimpleMultiply",
Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
CallbackTest("SimpleMultiplyFloat",
Pointer.fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat, 0.0)),
CallbackTest("ManyInts", Pointer.fromFunction<ManyIntsType>(manyInts, 0)),
CallbackTest(
"ManyDoubles", Pointer.fromFunction<ManyDoublesType>(manyDoubles, 0.0)),
CallbackTest("ManyArgs", Pointer.fromFunction<ManyArgsType>(manyArgs, 0.0)),
CallbackTest("Store", Pointer.fromFunction<StoreType>(store)),
CallbackTest(
"NullPointers", Pointer.fromFunction<NullPointersType>(nullPointers)),
CallbackTest("ReturnVoid", Pointer.fromFunction<ReturnVoid>(returnVoid)),
CallbackTest("ThrowExceptionDouble",
Pointer.fromFunction<ThrowExceptionDouble>(throwExceptionDouble, 42.0)),
CallbackTest("ThrowExceptionPointer",
Pointer.fromFunction<ThrowExceptionPointer>(throwExceptionPointer)),
CallbackTest("ThrowException",
Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
CallbackTest("TakeMaxUint8x10",
Pointer.fromFunction<TakeMaxUint8x10Type>(takeMaxUint8x10, 0)),
CallbackTest("ReturnMaxUint8",
Pointer.fromFunction<ReturnMaxUint8Type>(returnMaxUint8, 0)),
CallbackTest("ReturnMaxUint8",
Pointer.fromFunction<ReturnMaxUint8Type>(returnMaxUint8v2, 0)),
];
void main() {
testcases.forEach((t) => t.run());
}