// 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 #include #include #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 owned_snapshots_; // Loaded dynamic libraries. Dynamic libraries are loaded // when reading AOT snapshots. std::vector loaded_libraries_; // All isolates, started via Engine::StartIsolate. std::vector isolates_; // Stores per-isolate engine state. std::unordered_map> 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 DataForIsolate(Dart_Isolate isolate); }; } // namespace engine } // namespace dart #endif // RUNTIME_ENGINE_ENGINE_H_