Skip to content

Commit 6e33c95

Browse files
iinozemtsevCommit Queue
authored andcommitted
Dart Engine
Adds shared libraries for embedding Dart VM and new API (runtime/engine/include/dart_engine.h). TEST=tests/standalone/embedder_samples_test.dart Cq-Include-Trybots: luci.dart.try:vm-aot-android-release-arm64c-try,vm-aot-android-release-arm_x64-try,vm-aot-asan-linux-release-x64-try,vm-aot-dwarf-linux-product-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv32-try,vm-aot-linux-debug-simriscv64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-linux-product-x64-try,vm-aot-linux-release-arm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-release-x64-try,vm-aot-mac-product-arm64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-msan-linux-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-tsan-linux-release-x64-try,vm-aot-ubsan-linux-release-x64-try,vm-aot-win-debug-x64-try,vm-aot-win-debug-x64c-try,vm-aot-win-product-x64-try,vm-aot-win-release-x64-try,vm-appjit-linux-debug-x64-try,vm-appjit-linux-product-x64-try,vm-appjit-linux-release-x64-try,vm-asan-linux-release-arm64-try,vm-asan-linux-release-x64-try,vm-checked-mac-release-arm64-try,vm-eager-optimization-linux-release-ia32-try,vm-eager-optimization-linux-release-x64-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try,vm-ffi-android-product-arm-try,vm-ffi-android-product-arm64c-try,vm-ffi-android-release-arm-try,vm-ffi-android-release-arm64c-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-fuchsia-release-arm64-try,vm-fuchsia-release-x64-try,vm-gcc-linux-try,vm-linux-debug-ia32-try,vm-linux-debug-simriscv32-try,vm-linux-debug-simriscv64-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-linux-release-arm64-try,vm-linux-release-ia32-try,vm-linux-release-simarm-try,vm-linux-release-x64-try,vm-mac-debug-arm64-try,vm-mac-debug-x64-try,vm-mac-release-arm64-try,vm-mac-release-x64-try,vm-msan-linux-release-arm64-try,vm-msan-linux-release-x64-try,vm-msvc-windows-try,vm-reload-linux-debug-x64-try,vm-reload-linux-release-x64-try,vm-reload-rollback-linux-debug-x64-try,vm-reload-rollback-linux-release-x64-try,vm-tsan-linux-release-arm64-try,vm-tsan-linux-release-x64-try,vm-ubsan-linux-release-arm64-try,vm-ubsan-linux-release-x64-try,vm-win-debug-x64-try,vm-win-debug-x64c-try,vm-win-release-ia32-try,vm-win-release-x64-try Change-Id: Ia4e4d1b871ddef515cfb2f4639bdaa9fe3676936 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/402860 Reviewed-by: Slava Egorov <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 79df099 commit 6e33c95

31 files changed

+1633
-196
lines changed

BUILD.gn

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ group("runtime") {
5252
"runtime/bin:process_test",
5353
"runtime/bin:run_vm_tests",
5454
"runtime/vm:kernel_platform_files($host_toolchain)",
55-
"samples/embedder:all",
55+
"samples/embedder:kernel",
5656
"samples/ffi/http:fake_http",
5757
"utils/dartdev:dartdev",
5858
"utils/kernel-service:kernel-service",
@@ -67,6 +67,12 @@ group("runtime") {
6767
deps += [ "utils/kernel-service:frontend_server" ]
6868
}
6969

70+
# AOT samples use dlopen to load AOT snapshots and it works only on
71+
# 64-bit Linux right now.
72+
if (is_linux && (dart_target_arch == "x64" || dart_target_arch == "arm64")) {
73+
deps += [ "samples/embedder:aot" ]
74+
}
75+
7076
if (!is_win) {
7177
# The test isn't run on windows
7278
deps += [ "runtime/bin:entrypoints_verification_test" ]

build/rbe/rewrapper_dart.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ def parse_bootstrap_gen_kernel(self):
577577
'--no-embed-sources',
578578
'--no-link-platform',
579579
'--enable-asserts',
580+
'--link-platform',
580581
]:
581582
pass
582583
elif self.get_option(['--depfile']):

runtime/bin/BUILD.gn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,10 @@ source_set("dart_snapshot_cc") {
736736
}
737737

738738
source_set("dart_kernel_platform_cc") {
739-
visibility = [ ":*" ]
739+
visibility = [
740+
":*",
741+
"../engine:*",
742+
]
740743
deps = [
741744
":kernel_service_dill_linkable",
742745
":platform_strong_dill_linkable",

runtime/engine/BUILD.gn

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
# for details. All rights reserved. Use of this source code is governed by a
3+
# BSD-style license that can be found in the LICENSE file.
4+
5+
source_set("engine_jit_set") {
6+
include_dirs = [
7+
".",
8+
"..",
9+
"//third_party/boringssl/src/include",
10+
"//third_party",
11+
]
12+
13+
sources = [
14+
"../bin/dart_embedder_api_impl.cc",
15+
"../bin/vmservice_impl.cc",
16+
"../bin/vmservice_impl.h",
17+
"dart_engine_impl.cc",
18+
"engine.cc",
19+
"engine.h",
20+
]
21+
22+
configs += [
23+
"..:dart_arch_config",
24+
"..:dart_config",
25+
"..:dart_os_config",
26+
]
27+
28+
deps = [
29+
"..:libdart_jit",
30+
"../bin:dart_io_api",
31+
"../bin:dart_kernel_platform_cc",
32+
"../bin:libdart_builtin",
33+
]
34+
}
35+
36+
source_set("engine_aot_set") {
37+
include_dirs = [
38+
".",
39+
"..",
40+
"//third_party/boringssl/src/include",
41+
"//third_party",
42+
]
43+
44+
sources = [
45+
"../bin/dart_embedder_api_impl.cc",
46+
"../bin/vmservice_impl.cc",
47+
"../bin/vmservice_impl.h",
48+
"dart_engine_impl.cc",
49+
"engine.cc",
50+
"engine.h",
51+
]
52+
53+
configs += [
54+
"..:dart_aotruntime_config",
55+
"..:dart_arch_config",
56+
"..:dart_config",
57+
"..:dart_os_config",
58+
]
59+
60+
deps = [
61+
"..:libdart_aotruntime",
62+
"../bin:dart_io_api",
63+
"../bin:libdart_builtin",
64+
]
65+
}
66+
67+
shared_library("dart_engine_jit_shared") {
68+
deps = [ ":engine_jit_set" ]
69+
70+
if (is_mac) {
71+
ldflags = [ "-Wl,-install_name,@rpath/libdart_engine_jit_shared.dylib" ]
72+
}
73+
74+
if (is_win) {
75+
ldflags = [ "/EXPORT:Dart_True" ]
76+
77+
libs = [
78+
"ole32.lib",
79+
"iphlpapi.lib",
80+
"psapi.lib",
81+
"ws2_32.lib",
82+
"Rpcrt4.lib",
83+
"shlwapi.lib",
84+
"winmm.lib",
85+
]
86+
}
87+
}
88+
89+
shared_library("dart_engine_aot_shared") {
90+
deps = [ ":engine_aot_set" ]
91+
92+
if (is_mac) {
93+
ldflags = [ "-Wl,-install_name,@rpath/libdart_engine_aot_shared.dylib" ]
94+
}
95+
96+
if (is_win) {
97+
ldflags = [ "/EXPORT:Dart_True" ]
98+
99+
libs = [
100+
"ole32.lib",
101+
"iphlpapi.lib",
102+
"psapi.lib",
103+
"ws2_32.lib",
104+
"Rpcrt4.lib",
105+
"shlwapi.lib",
106+
"winmm.lib",
107+
]
108+
}
109+
}

runtime/engine/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dart Engine
2+
3+
The `include/dart_engine.h` provides additional functions to embed the Dart VM
4+
and to call Dart functions from kernel and AOT snapshots. It is not intended to
5+
be a full-featured API, and should be used together with `dart_api.h`.
6+
7+
It is intended for reusing of existing Dart code in non-Dart programs, and
8+
allows to use Dart snapshots as shared libraries: the caller can start one or
9+
several isolates from Dart snapshots and call Dart functions from it.
10+
11+
Comparing to `dart_api.h` it brings the following:
12+
13+
- Full initialization of Dart VM, including initializing core libraries.
14+
- Easier handling of isolate messages
15+
- Lock-guarded functions to enter/exit isolates.
16+
17+
See examples in `samples/embedder` for usages of the API.
18+
19+
## Handling isolate messages
20+
21+
In `dart_api.h` there are two possible ways to handle asynchronous
22+
isolate messages:
23+
24+
- `Dart_MessageNotifyCallback`: Users can pass a callback to get
25+
notifications about messages to handle, but handling messages still
26+
requires entering an isolate, entering a scope, calling
27+
`Dart_HandleMessage`, and then leaving a scope and an isolate.
28+
- `Dart_RunLoop`: Users can invoke it on a separate thread, but then they won't
29+
be able to enter isolates from other threads.
30+
31+
As an alternative, `dart_engine.h` provides a simpler function
32+
`DartEngine_HandleMessage`, which encapsulates isolate and scope management, and
33+
it allows to specify per isolate / default message schedulers, which only need
34+
to schedule an execution `DartEngine_HandleMessage` with the right isolate.
35+
36+
Users can create their own `DartEngine_MessageScheduler` struct and pass it to
37+
`DartEngine_SetMessageScheduler` / `DartEngine_SetDefaultMessageScheduler`. See
38+
`samples/embedder/run_timer_async.cc` and `samples/embedder/run_timer.cc`
39+
examples.
40+
41+
## Entering / leaving isolates
42+
43+
Because engine API uses its own message handling, it is important to use
44+
`DartEngine_AcquireIsolate` / `DartEngine_ReleaseIsolate` instead of
45+
`Dart_EnterIsolate` / `Dart_ExitIsolate`. `DartEngine_AcquireIsolate` blocks
46+
until an isolate can be entered by trying to obtain an internal lock (which is
47+
released by `DartEngine_ReleaseIsolate`), while `Dart_EnterIsolate` crashes if
48+
some other thread has entered the same isolate.

runtime/engine/dart_engine_impl.cc

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
#include <cstdint>
6+
#include <memory>
7+
#include <vector>
8+
#include "engine/engine.h"
9+
#include "include/dart_api.h"
10+
#include "include/dart_engine.h"
11+
#include "platform/utils.h"
12+
13+
namespace dart {
14+
namespace engine {
15+
16+
DART_EXPORT bool DartEngine_Init(char** error) {
17+
return Engine::instance()->Initialize(error);
18+
}
19+
20+
DART_EXPORT void DartEngine_Shutdown() {
21+
Engine::instance()->Shutdown();
22+
}
23+
24+
DART_EXPORT DartEngine_SnapshotData DartEngine_KernelFromFile(const char* path,
25+
char** error) {
26+
return Engine::instance()->KernelFromFile(path, error);
27+
}
28+
29+
DART_EXPORT DartEngine_SnapshotData
30+
DartEngine_AotSnapshotFromFile(const char* path, char** error) {
31+
return Engine::instance()->AotFromFile(path, error);
32+
}
33+
34+
DART_EXPORT Dart_Isolate
35+
DartEngine_CreateIsolate(DartEngine_SnapshotData snapshot_data, char** error) {
36+
if (!Engine::instance()->Initialize(error)) {
37+
return nullptr;
38+
}
39+
return Engine::instance()->StartIsolate(snapshot_data, error);
40+
}
41+
42+
DART_EXPORT void DartEngine_AcquireIsolate(Dart_Isolate isolate) {
43+
Engine::instance()->LockIsolate(isolate);
44+
Dart_EnterIsolate(isolate);
45+
}
46+
47+
DART_EXPORT void DartEngine_ReleaseIsolate() {
48+
Dart_Isolate current = Dart_CurrentIsolate();
49+
ASSERT(current != nullptr);
50+
Dart_ExitIsolate();
51+
Engine::instance()->UnlockIsolate(current);
52+
}
53+
54+
DART_EXPORT void DartEngine_SetHandleMessageErrorCallback(
55+
DartEngine_HandleMessageErrorCallback handle_message_error_callback) {
56+
Engine::instance()->SetHandleMessageErrorCallback(
57+
handle_message_error_callback);
58+
}
59+
60+
DART_EXPORT void DartEngine_SetDefaultMessageScheduler(
61+
DartEngine_MessageScheduler scheduler) {
62+
Engine::instance()->SetDefaultMessageScheduler(scheduler);
63+
}
64+
65+
DART_EXPORT void DartEngine_SetMessageScheduler(
66+
DartEngine_MessageScheduler scheduler,
67+
Dart_Isolate isolate) {
68+
Engine::instance()->SetMessageScheduler(scheduler, isolate);
69+
}
70+
71+
DART_EXPORT void DartEngine_HandleMessage(Dart_Isolate isolate) {
72+
Engine::instance()->HandleMessage(isolate);
73+
}
74+
75+
} // namespace engine
76+
} // namespace dart

0 commit comments

Comments
 (0)