Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 225a301

Browse files
sjindel-googlecommit-bot@chromium.org
authored andcommitted
[vm/ffi] Re-land "[vm/ffi] FFI callbacks on X64."
There are minor fixes for dartkb and windows. The original revision is in patchset 1. Change-Id: I9ab6e5fdb33fb4e84ea520c283fe94323616a8ce Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103129 Commit-Queue: Samir Jindel <[email protected]> Auto-Submit: Samir Jindel <[email protected]> Reviewed-by: Daco Harkes <[email protected]>
1 parent edadc9c commit 225a301

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1470
-190
lines changed

pkg/vm/lib/transformations/ffi_use_sites.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,10 @@ class _FfiUseSiteTransformer extends FfiTransformer {
275275
}
276276

277277
bool _isStatic(Expression node) {
278-
if (node is! StaticGet) return false;
279-
280-
return (node as StaticGet).target is Procedure;
278+
if (node is StaticGet) {
279+
return node.target is Procedure;
280+
}
281+
return node is ConstantExpression;
281282
}
282283
}
283284

runtime/bin/ffi_test_functions.cc

Lines changed: 218 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@
77
#include <stddef.h>
88
#include <stdlib.h>
99
#include <sys/types.h>
10+
#include <csignal>
1011

1112
#include "platform/assert.h"
1213
#include "platform/globals.h"
14+
#include "vm/os_thread.h"
1315
#if defined(HOST_OS_WINDOWS)
1416
#include <psapi.h>
1517
#else
1618
#include <unistd.h>
1719
#endif
1820

21+
#include <setjmp.h>
22+
#include <signal.h>
1923
#include <iostream>
2024
#include <limits>
2125

2226
#include "include/dart_api.h"
2327

2428
namespace dart {
2529

30+
////////////////////////////////////////////////////////////////////////////////
31+
// Tests for Dart -> native calls.
32+
2633
// Sums two ints and adds 42.
2734
// Simple function to test trampolines.
2835
// Also used for testing argument exception on passing null instead of a Dart
@@ -449,7 +456,8 @@ DART_EXPORT float InventFloatValue() {
449456
return retval;
450457
}
451458

452-
// Functions for stress-testing GC by returning values that require boxing.
459+
////////////////////////////////////////////////////////////////////////////////
460+
// Functions for stress-testing.
453461

454462
DART_EXPORT int64_t MinInt64() {
455463
return 0x8000000000000000;
@@ -511,4 +519,213 @@ DART_EXPORT int RedirectStderr() {
511519
}
512520
#endif
513521

522+
////////////////////////////////////////////////////////////////////////////////
523+
// Tests for callbacks.
524+
525+
#define CHECK(X) \
526+
if (!(X)) { \
527+
fprintf(stderr, "%s\n", "Check failed: " #X); \
528+
return 1; \
529+
}
530+
531+
#define CHECK_EQ(X, Y) CHECK((X) == (Y))
532+
533+
// Sanity test.
534+
DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
535+
CHECK_EQ(add(10, 20), 30);
536+
return 0;
537+
}
538+
539+
//// Following tests are copied from above, with the role of Dart and C++ code
540+
//// reversed.
541+
542+
DART_EXPORT int TestIntComputation(
543+
int64_t (*fn)(int8_t, int16_t, int32_t, int64_t)) {
544+
CHECK_EQ(fn(125, 250, 500, 1000), 625);
545+
CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
546+
CHECK_EQ(((int64_t)-0x8000000000000000LL),
547+
fn(0, 0, 0, -0x8000000000000000LL));
548+
return 0;
549+
}
550+
551+
DART_EXPORT int TestUintComputation(
552+
uint64_t (*fn)(uint8_t, uint16_t, uint32_t, uint64_t)) {
553+
CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
554+
CHECK_EQ(-0x8000000000000000LL, fn(0, 0, 0, -0x8000000000000000LL));
555+
CHECK_EQ(-1, (int64_t)fn(0, 0, 0, -1));
556+
return 0;
557+
}
558+
559+
DART_EXPORT int TestSimpleMultiply(double (*fn)(double)) {
560+
CHECK_EQ(fn(2.0), 2.0 * 1.337);
561+
return 0;
562+
}
563+
564+
DART_EXPORT int TestSimpleMultiplyFloat(float (*fn)(float)) {
565+
CHECK(std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
566+
return 0;
567+
}
568+
569+
DART_EXPORT int TestManyInts(intptr_t (*fn)(intptr_t,
570+
intptr_t,
571+
intptr_t,
572+
intptr_t,
573+
intptr_t,
574+
intptr_t,
575+
intptr_t,
576+
intptr_t,
577+
intptr_t,
578+
intptr_t)) {
579+
CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
580+
return 0;
581+
}
582+
583+
DART_EXPORT int TestManyDoubles(double (*fn)(double,
584+
double,
585+
double,
586+
double,
587+
double,
588+
double,
589+
double,
590+
double,
591+
double,
592+
double)) {
593+
CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
594+
return 0;
595+
}
596+
597+
DART_EXPORT int TestManyArgs(double (*fn)(intptr_t a,
598+
float b,
599+
intptr_t c,
600+
double d,
601+
intptr_t e,
602+
float f,
603+
intptr_t g,
604+
double h,
605+
intptr_t i,
606+
float j,
607+
intptr_t k,
608+
double l,
609+
intptr_t m,
610+
float n,
611+
intptr_t o,
612+
double p,
613+
intptr_t q,
614+
float r,
615+
intptr_t s,
616+
double t)) {
617+
CHECK(210.0 == fn(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0,
618+
15, 16.0, 17, 18.0, 19, 20.0));
619+
return 0;
620+
}
621+
622+
DART_EXPORT int TestStore(int64_t* (*fn)(int64_t* a)) {
623+
int64_t p[2] = {42, 1000};
624+
int64_t* result = fn(p);
625+
CHECK_EQ(*result, 1337);
626+
CHECK_EQ(p[1], 1337);
627+
CHECK_EQ(result, p + 1);
628+
return 0;
629+
}
630+
631+
DART_EXPORT int TestReturnNull(int32_t fn()) {
632+
CHECK_EQ(fn(), 0);
633+
return 0;
634+
}
635+
636+
DART_EXPORT int TestNullPointers(int64_t* (*fn)(int64_t* ptr)) {
637+
CHECK_EQ(fn(nullptr), nullptr);
638+
int64_t p[2] = {0};
639+
CHECK_EQ(fn(p), p + 1);
640+
return 0;
641+
}
642+
643+
struct CallbackTestData {
644+
int success;
645+
void (*callback)();
646+
};
647+
648+
#if defined(TARGET_OS_LINUX) && !defined(PRODUCT)
649+
650+
thread_local sigjmp_buf buf;
651+
void CallbackTestSignalHandler(int) {
652+
siglongjmp(buf, 1);
653+
}
654+
655+
int ExpectAbort(void (*fn)()) {
656+
fprintf(stderr, "**** EXPECT STACKTRACE TO FOLLOW. THIS IS OK. ****\n");
657+
658+
struct sigaction old_action;
659+
int result = __sigsetjmp(buf, /*savesigs=*/1);
660+
if (result == 0) {
661+
// Install signal handler.
662+
struct sigaction handler;
663+
handler.sa_handler = CallbackTestSignalHandler;
664+
sigemptyset(&handler.sa_mask);
665+
handler.sa_flags = 0;
666+
667+
sigaction(SIGABRT, &handler, &old_action);
668+
669+
fn();
670+
} else {
671+
// Caught the setjmp.
672+
sigaction(SIGABRT, &old_action, NULL);
673+
exit(0);
674+
}
675+
fprintf(stderr, "Expected abort!!!\n");
676+
exit(1);
677+
}
678+
679+
void* TestCallbackOnThreadOutsideIsolate(void* parameter) {
680+
CallbackTestData* data = reinterpret_cast<CallbackTestData*>(parameter);
681+
data->success = ExpectAbort(data->callback);
682+
return NULL;
683+
}
684+
685+
int TestCallbackOtherThreadHelper(void* (*tester)(void*), void (*fn)()) {
686+
CallbackTestData data = {1, fn};
687+
688+
pthread_attr_t attr;
689+
int result = pthread_attr_init(&attr);
690+
CHECK_EQ(result, 0);
691+
692+
pthread_t tid;
693+
result = pthread_create(&tid, &attr, tester, &data);
694+
CHECK_EQ(result, 0);
695+
696+
result = pthread_attr_destroy(&attr);
697+
CHECK_EQ(result, 0);
698+
699+
void* retval;
700+
result = pthread_join(tid, &retval);
701+
702+
// Doesn't actually return because the other thread will exit when the test is
703+
// finished.
704+
UNREACHABLE();
705+
}
706+
707+
// Run a callback on another thread and verify that it triggers SIGABRT.
708+
DART_EXPORT int TestCallbackWrongThread(void (*fn)()) {
709+
return TestCallbackOtherThreadHelper(&TestCallbackOnThreadOutsideIsolate, fn);
710+
}
711+
712+
// Verify that we get SIGABRT when invoking a native callback outside an
713+
// isolate.
714+
DART_EXPORT int TestCallbackOutsideIsolate(void (*fn)()) {
715+
Dart_Isolate current = Dart_CurrentIsolate();
716+
717+
Dart_ExitIsolate();
718+
CallbackTestData data = {1, fn};
719+
TestCallbackOnThreadOutsideIsolate(&data);
720+
Dart_EnterIsolate(current);
721+
722+
return data.success;
723+
}
724+
725+
DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
726+
return ExpectAbort(fn);
727+
}
728+
729+
#endif // defined(TARGET_OS_LINUX) && !defined(PRODUCT)
730+
514731
} // namespace dart

0 commit comments

Comments
 (0)