| // Copyright (c) 2025, 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. |
| |
| #ifndef RUNTIME_ENGINE_ENGINE_H_ |
| #define RUNTIME_ENGINE_ENGINE_H_ |
| |
| #include <memory> |
| #include <unordered_map> |
| #include <vector> |
| #include "include/dart_engine.h" |
| #include "platform/synchronization.h" |
| |
| namespace dart { |
| namespace engine { |
| |
| // Manages Dart VM initialization/shutdown, isolates, and all state that needs |
| // to be disposed (e.g. buffers of loaded snapshots). |
| // |
| // Since Dart VM has a global state, there should be only one instance of this |
| // class (accessible through Engine::instance()). |
| class Engine { |
| public: |
| // Loads Kernel snapshot from given file path. |
| // |
| // Just reads all bytes into a single buffer, owned by this class. |
| DartEngine_SnapshotData KernelFromFile(const char* path, char** error); |
| |
| // Loads AOT snapshot from given file path. |
| // |
| // Opens given AOT snapshot as a shared library and loads buffer symbols from |
| // it. |
| DartEngine_SnapshotData AotFromFile(const char* path, char** error); |
| |
| // Starts an isolate from a snapshot. |
| // |
| // Starting an isolate also routes message notify callback to NotifyMessage. |
| Dart_Isolate StartIsolate(const DartEngine_SnapshotData snapshot, |
| char** error); |
| |
| // Acquires a lock for an isolate, so that the thread can enter it. |
| void LockIsolate(Dart_Isolate isolate); |
| |
| // Releases the lock obtained by LockIsolate. |
| void UnlockIsolate(Dart_Isolate isolate); |
| |
| // Called by Dart VM via Engine::MessageNotifyCallback. |
| // |
| // Calls isolate-specific message scheduler (if any), default message |
| // scheduler, or ignores the message. |
| void NotifyMessage(Dart_Isolate isolate); |
| |
| // Calls Dart_HandleMessage, managing an isolate lock and Dart scope. |
| void HandleMessage(Dart_Isolate isolate); |
| |
| // Drains the microtasks queue, requires an active isolate. |
| Dart_Handle DrainMicrotasksQueue(); |
| |
| // Sets a callback to be called when Dart_HandleMessage returns an error. |
| void SetHandleMessageErrorCallback( |
| DartEngine_HandleMessageErrorCallback callback); |
| |
| // Sets a message scheduler for a given isolate. |
| void SetDefaultMessageScheduler(DartEngine_MessageScheduler scheduler); |
| |
| // Sets default message scheduler for isolates without dedicated |
| // message scheduler. |
| void SetMessageScheduler(DartEngine_MessageScheduler scheduler, |
| Dart_Isolate isolate); |
| |
| // Initializes embedder and partially initializes Dart VM. |
| // |
| // Full initialization happens only when the user starts the first isolate, as |
| // in case of AOT snapshots we don't have vm snapshot data and vm snapshot |
| // instuructions before the user makes the first call to StartIsolate. |
| bool Initialize(char** error); |
| |
| // Shuts down the engine. |
| // |
| // Once shut down, it is not supposed to be re-initialized. |
| void Shutdown(); |
| |
| static Engine* instance(); |
| // Passed to Dart_SetMessageNotifyCallback. |
| static void MessageNotifyCallback(Dart_Isolate isolate); |
| // Passed to user-previded message scheduler callback. |
| static void HandleMessageCallback(Dart_Isolate isolate); |
| |
| private: |
| // Engine's internal data for isolate. |
| struct IsolateData { |
| DartEngine_MessageScheduler scheduler; |
| Mutex mutex; |
| Dart_PersistentHandle isolate_library; |
| Dart_PersistentHandle drain_microtasks_function_name; |
| }; |
| |
| // Set to false once shutdown starts. |
| bool is_running_ = false; |
| |
| // Controls initalization and shutdown, and prevents deadlocks when delivering |
| // messages during shutdown. |
| Mutex engine_lifecycle_; |
| |
| // Guards access to engine state. |
| Mutex engine_state_; |
| |
| // Whether Engine::Initialize is called. |
| bool initialized_ = false; |
| |
| // Added because of AOT mode, because in AOT mode Dart VM cannot be fully |
| // initialized until we get vm snapshot data, which we typically get when the |
| // user starts the first isolate. |
| bool first_isolate_started_ = false; |
| |
| // Snapshots, whose buffers are owned by the engine. |
| // and are freed on Shutdown. |
| std::vector<DartEngine_SnapshotData> owned_snapshots_; |
| |
| // Loaded dynamic libraries. Dynamic libraries are loaded |
| // when reading AOT snapshots. |
| std::vector<void*> loaded_libraries_; |
| |
| // All isolates, started via Engine::StartIsolate. |
| std::vector<Dart_Isolate> isolates_; |
| |
| // Stores per-isolate engine state. |
| std::unordered_map<Dart_Isolate, std::shared_ptr<IsolateData>> isolate_data_; |
| |
| // Default scheduler. |
| DartEngine_MessageScheduler default_scheduler_; |
| |
| // Callback to notify about Dart_HandleMessage errors. |
| DartEngine_HandleMessageErrorCallback handle_message_error_callback_; |
| |
| // Helper function to get an element from isolate_data_. |
| std::shared_ptr<IsolateData> DataForIsolate(Dart_Isolate isolate); |
| }; |
| |
| } // namespace engine |
| } // namespace dart |
| #endif // RUNTIME_ENGINE_ENGINE_H_ |