2019-03-05 14:17:08 +00:00
|
|
|
// 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.
|
|
|
|
//
|
2021-05-21 07:04:37 +00:00
|
|
|
// VMOptions=--deterministic --optimization-counter-threshold=500
|
|
|
|
// VMOptions=--deterministic --optimization-counter-threshold=-1
|
|
|
|
// VMOptions=--deterministic --optimization-counter-threshold=500 --no-dual-map-code --write-protect-code
|
|
|
|
// VMOptions=--deterministic --optimization-counter-threshold=-1 --no-dual-map-code --write-protect-code
|
|
|
|
// VMOptions=--no-dual-map-code --write-protect-code
|
|
|
|
// VMOptions=--no-dual-map-code --write-protect-code --stacktrace-every=100
|
2019-03-05 14:17:08 +00:00
|
|
|
//
|
2019-03-15 12:38:54 +00:00
|
|
|
// Dart test program for stress-testing boxing and GC in return paths from FFI
|
|
|
|
// trampolines.
|
|
|
|
//
|
2019-03-05 14:17:08 +00:00
|
|
|
// NOTE: This test does not produce useful stderr when it fails because the
|
|
|
|
// stderr is redirected to a file for reflection.
|
2019-03-25 16:14:18 +00:00
|
|
|
//
|
|
|
|
// SharedObjects=ffi_test_functions
|
2019-03-05 14:17:08 +00:00
|
|
|
|
|
|
|
import 'dart:ffi' as ffi;
|
|
|
|
import "package:expect/expect.dart";
|
2019-06-17 10:47:00 +00:00
|
|
|
import 'ffi_test_helpers.dart';
|
2019-03-05 14:17:08 +00:00
|
|
|
|
|
|
|
main() async {
|
2019-06-06 15:52:12 +00:00
|
|
|
testBoxInt64();
|
|
|
|
testBoxInt32();
|
|
|
|
testBoxDouble();
|
|
|
|
testBoxPointer();
|
|
|
|
testAllocateInNative();
|
2019-06-14 16:54:23 +00:00
|
|
|
testRegress37069();
|
2019-08-07 11:37:20 +00:00
|
|
|
testWriteProtection();
|
2019-03-05 14:17:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef NativeNullaryOp64 = ffi.Int64 Function();
|
|
|
|
typedef NativeNullaryOp32 = ffi.Int32 Function();
|
|
|
|
typedef NativeNullaryOpDouble = ffi.Double Function();
|
|
|
|
typedef NativeNullaryOpPtr = ffi.Pointer<ffi.Void> Function();
|
2019-04-11 11:59:54 +00:00
|
|
|
typedef NativeUnaryOp = ffi.Void Function(ffi.Uint64);
|
2019-06-13 16:26:40 +00:00
|
|
|
typedef NativeUndenaryOp = ffi.Uint64 Function(
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64,
|
|
|
|
ffi.Uint64);
|
2019-03-05 14:17:08 +00:00
|
|
|
typedef NullaryOp = int Function();
|
|
|
|
typedef NullaryOpDbl = double Function();
|
|
|
|
typedef NullaryOpPtr = ffi.Pointer<ffi.Void> Function();
|
2019-04-11 11:59:54 +00:00
|
|
|
typedef UnaryOp = void Function(int);
|
2019-06-13 16:26:40 +00:00
|
|
|
typedef UndenaryOp = int Function(
|
|
|
|
int, int, int, int, int, int, int, int, int, int, int);
|
2019-03-05 14:17:08 +00:00
|
|
|
|
2019-03-15 12:38:54 +00:00
|
|
|
//// These functions return values that require boxing into different types.
|
|
|
|
|
2019-03-05 14:17:08 +00:00
|
|
|
final minInt64 =
|
|
|
|
ffiTestFunctions.lookupFunction<NativeNullaryOp64, NullaryOp>("MinInt64");
|
|
|
|
|
2019-03-15 12:38:54 +00:00
|
|
|
// Forces boxing into Mint on all platforms.
|
2019-03-05 14:17:08 +00:00
|
|
|
void testBoxInt64() {
|
|
|
|
Expect.equals(0x8000000000000000, minInt64());
|
|
|
|
}
|
|
|
|
|
|
|
|
NullaryOp minInt32 =
|
|
|
|
ffiTestFunctions.lookupFunction<NativeNullaryOp32, NullaryOp>("MinInt32");
|
|
|
|
|
2019-03-15 12:38:54 +00:00
|
|
|
// Forces boxing into Mint on 32-bit platforms only.
|
2019-03-05 14:17:08 +00:00
|
|
|
void testBoxInt32() {
|
2019-03-15 12:38:54 +00:00
|
|
|
Expect.equals(-0x80000000, minInt32());
|
2019-03-05 14:17:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
final smallDouble = ffiTestFunctions
|
|
|
|
.lookupFunction<NativeNullaryOpDouble, NullaryOpDbl>("SmallDouble");
|
|
|
|
|
2019-03-15 12:38:54 +00:00
|
|
|
// Forces boxing into Double.
|
2019-03-05 14:17:08 +00:00
|
|
|
void testBoxDouble() {
|
|
|
|
Expect.equals(0x80000000 * -1.0, smallDouble());
|
|
|
|
}
|
|
|
|
|
2019-03-15 12:38:54 +00:00
|
|
|
final largePointer = ffiTestFunctions
|
|
|
|
.lookupFunction<NativeNullaryOpPtr, NullaryOpPtr>("LargePointer");
|
|
|
|
|
2019-03-20 17:45:23 +00:00
|
|
|
// Forces boxing into ffi.Pointer and ffi.Mint.
|
|
|
|
void testBoxPointer() {
|
|
|
|
ffi.Pointer pointer = largePointer();
|
[vm/ffi] Split out tests which use nulls
Issue: https://github.com/dart-lang/sdk/issues/40233
Change-Id: If4e79995f13ed2870f4663ceac5500ceacbe04df
Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132602
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-01-20 16:01:08 +00:00
|
|
|
if (ffi.sizeOf<ffi.Pointer>() == 4) {
|
|
|
|
Expect.equals(0x82000000, pointer.address);
|
|
|
|
} else {
|
|
|
|
Expect.equals(0x8100000082000000, pointer.address);
|
2019-03-20 17:45:23 +00:00
|
|
|
}
|
2019-03-15 12:38:54 +00:00
|
|
|
}
|
2019-04-11 11:59:54 +00:00
|
|
|
|
2019-06-06 15:52:12 +00:00
|
|
|
// Test GC in the FFI call path by calling a C function which triggers GC
|
|
|
|
// directly.
|
|
|
|
void testAllocateInNative() => triggerGc();
|
2019-06-17 10:47:00 +00:00
|
|
|
|
2019-06-13 16:26:40 +00:00
|
|
|
// This also works as a regression test for 37176.
|
|
|
|
|
|
|
|
final regress37069 = ffiTestFunctions
|
|
|
|
.lookupFunction<NativeUndenaryOp, UndenaryOp>("Regress37069");
|
|
|
|
|
|
|
|
// Test GC in the FFI call path by calling a C function which triggers GC
|
|
|
|
// directly.
|
|
|
|
void testRegress37069() {
|
|
|
|
regress37069(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
|
|
|
}
|
2019-08-07 11:37:20 +00:00
|
|
|
|
2019-08-08 10:07:42 +00:00
|
|
|
final unprotectCode = ffiTestFunctions.lookupFunction<
|
2019-08-21 13:33:37 +00:00
|
|
|
ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>),
|
|
|
|
ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>("TestUnprotectCode");
|
2019-08-08 10:07:42 +00:00
|
|
|
final waitForHelper = ffiTestFunctions.lookupFunction<
|
|
|
|
ffi.Void Function(ffi.Pointer<ffi.Void>),
|
2019-08-09 08:32:50 +00:00
|
|
|
void Function(ffi.Pointer<ffi.Void>)>("WaitForHelper");
|
2019-08-07 11:37:20 +00:00
|
|
|
|
|
|
|
void testWriteProtection() {
|
2019-08-21 13:33:37 +00:00
|
|
|
waitForHelper(unprotectCode(ffi.nullptr));
|
2019-08-07 11:37:20 +00:00
|
|
|
}
|