cdd8311b14
Tested: Test added for fix. Change-Id: Ifbefb01ef0caf9de80e44c44e5de4cc51bb129cc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/489080 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
147 lines
5.0 KiB
C++
147 lines
5.0 KiB
C++
// 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.
|
|
//
|
|
// If a microtask throws, the error is returned to the caller,
|
|
// and the queue may still contain more entries.
|
|
// The caller should continue to drain the queue after handling the error.
|
|
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_
|