blob: 389ffa4686651431fae16f041fe1fa5bbce18b6b [file] [log] [blame] [edit]
// 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_