未验证 提交 0d6ff166 编写于 作者: C Chinmay Garde 提交者: GitHub

Shut down and restart the Dart VM as needed. (#7832)

The shell was already designed to cleanly shut down the VM but it couldnt
earlier as |Dart_Initialize| could never be called after a |Dart_Cleanup|. This
meant that shutting down an engine instance could not shut down the VM to save
memory because newly created engines in the process after that point couldn't
restart the VM. There can only be one VM running in a process at a time.

This patch separate the previous DartVM object into one that references a
running instance of the DartVM and a set of immutable dependencies that
components can reference even as the VM is shutting down.

Unit tests have been added to assert that non-overlapping engine launches use
difference VM instances.
上级 256db4bc
......@@ -355,6 +355,10 @@ FILE: ../../../flutter/runtime/dart_snapshot_buffer.cc
FILE: ../../../flutter/runtime/dart_snapshot_buffer.h
FILE: ../../../flutter/runtime/dart_vm.cc
FILE: ../../../flutter/runtime/dart_vm.h
FILE: ../../../flutter/runtime/dart_vm_data.cc
FILE: ../../../flutter/runtime/dart_vm_data.h
FILE: ../../../flutter/runtime/dart_vm_lifecycle.cc
FILE: ../../../flutter/runtime/dart_vm_lifecycle.h
FILE: ../../../flutter/runtime/dart_vm_unittests.cc
FILE: ../../../flutter/runtime/embedder_resources.cc
FILE: ../../../flutter/runtime/embedder_resources.h
......
......@@ -14,8 +14,10 @@ namespace blink {
Dart_Handle IsolateNameServerNatives::LookupPortByName(
const std::string& name) {
IsolateNameServer* name_server =
UIDartState::Current()->GetIsolateNameServer();
auto name_server = UIDartState::Current()->GetIsolateNameServer();
if (!name_server) {
return Dart_Null();
}
Dart_Port port = name_server->LookupIsolatePortByName(name);
if (port == ILLEGAL_PORT) {
return Dart_Null();
......@@ -26,8 +28,10 @@ Dart_Handle IsolateNameServerNatives::LookupPortByName(
Dart_Handle IsolateNameServerNatives::RegisterPortWithName(
Dart_Handle port_handle,
const std::string& name) {
IsolateNameServer* name_server =
UIDartState::Current()->GetIsolateNameServer();
auto name_server = UIDartState::Current()->GetIsolateNameServer();
if (!name_server) {
return Dart_False();
}
Dart_Port port = ILLEGAL_PORT;
Dart_SendPortGetId(port_handle, &port);
if (!name_server->RegisterIsolatePortWithName(port, name)) {
......@@ -38,8 +42,10 @@ Dart_Handle IsolateNameServerNatives::RegisterPortWithName(
Dart_Handle IsolateNameServerNatives::RemovePortNameMapping(
const std::string& name) {
IsolateNameServer* name_server =
UIDartState::Current()->GetIsolateNameServer();
auto name_server = UIDartState::Current()->GetIsolateNameServer();
if (!name_server) {
return Dart_False();
}
if (!name_server->RemoveIsolateNameMapping(name)) {
return Dart_False();
}
......
......@@ -23,7 +23,7 @@ UIDartState::UIDartState(
std::string advisory_script_entrypoint,
std::string logger_prefix,
UnhandledExceptionCallback unhandled_exception_callback,
IsolateNameServer* isolate_name_server)
std::shared_ptr<IsolateNameServer> isolate_name_server)
: task_runners_(std::move(task_runners)),
add_callback_(std::move(add_callback)),
remove_callback_(std::move(remove_callback)),
......@@ -33,7 +33,7 @@ UIDartState::UIDartState(
advisory_script_entrypoint_(std::move(advisory_script_entrypoint)),
logger_prefix_(std::move(logger_prefix)),
unhandled_exception_callback_(unhandled_exception_callback),
isolate_name_server_(isolate_name_server) {
isolate_name_server_(std::move(isolate_name_server)) {
AddOrRemoveTaskObserver(true /* add */);
}
......@@ -124,7 +124,7 @@ fml::WeakPtr<GrContext> UIDartState::GetResourceContext() const {
return io_manager_->GetResourceContext();
}
IsolateNameServer* UIDartState::GetIsolateNameServer() {
std::shared_ptr<IsolateNameServer> UIDartState::GetIsolateNameServer() const {
return isolate_name_server_;
}
......
......@@ -53,7 +53,7 @@ class UIDartState : public tonic::DartState {
fml::WeakPtr<GrContext> GetResourceContext() const;
IsolateNameServer* GetIsolateNameServer();
std::shared_ptr<IsolateNameServer> GetIsolateNameServer() const;
tonic::DartErrorHandleType GetLastError();
......@@ -81,7 +81,7 @@ class UIDartState : public tonic::DartState {
std::string advisory_script_entrypoint,
std::string logger_prefix,
UnhandledExceptionCallback unhandled_exception_callback,
IsolateNameServer* isolate_name_server);
std::shared_ptr<IsolateNameServer> isolate_name_server);
~UIDartState() override;
......@@ -107,7 +107,7 @@ class UIDartState : public tonic::DartState {
std::unique_ptr<Window> window_;
tonic::DartMicrotaskQueue microtask_queue_;
UnhandledExceptionCallback unhandled_exception_callback_;
IsolateNameServer* isolate_name_server_;
const std::shared_ptr<IsolateNameServer> isolate_name_server_;
void AddOrRemoveTaskObserver(bool add);
};
......
......@@ -36,6 +36,10 @@ source_set("runtime") {
"dart_snapshot_buffer.h",
"dart_vm.cc",
"dart_vm.h",
"dart_vm_data.cc",
"dart_vm_data.h",
"dart_vm_lifecycle.cc",
"dart_vm_lifecycle.h",
"embedder_resources.cc",
"embedder_resources.h",
"runtime_controller.cc",
......@@ -73,7 +77,9 @@ source_set("runtime") {
flutter_runtime_mode != "dynamic_release" && !is_fuchsia) {
# Only link in Observatory in non-release modes on non-Fuchsia. Fuchsia
# instead puts Observatory into the runner's package.
deps += [ "//third_party/dart/runtime/observatory:embedded_observatory_archive" ]
deps += [
"//third_party/dart/runtime/observatory:embedded_observatory_archive",
]
}
}
......@@ -95,6 +101,7 @@ executable("runtime_unittests") {
":runtime_fixtures",
"$flutter_root/fml",
"$flutter_root/lib/snapshot",
"$flutter_root/shell/common",
"$flutter_root/testing",
"//third_party/dart/runtime:libdart_jit",
"//third_party/skia",
......
......@@ -14,6 +14,7 @@
#include "flutter/lib/ui/dart_ui.h"
#include "flutter/runtime/dart_service_isolate.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#include "third_party/tonic/converter/dart_converter.h"
......@@ -29,9 +30,9 @@
namespace blink {
std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
......@@ -50,7 +51,7 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
// isolate lifecycle is entirely managed by the VM).
auto root_embedder_data = std::make_unique<std::shared_ptr<DartIsolate>>(
std::make_shared<DartIsolate>(
vm, // VM
settings, // settings
std::move(isolate_snapshot), // isolate snapshot
std::move(shared_snapshot), // shared snapshot
task_runners, // task runners
......@@ -93,9 +94,9 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
return embedder_isolate;
}
DartIsolate::DartIsolate(DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
DartIsolate::DartIsolate(const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
......@@ -103,36 +104,31 @@ DartIsolate::DartIsolate(DartVM* vm,
std::string advisory_script_entrypoint,
ChildIsolatePreparer child_isolate_preparer)
: UIDartState(std::move(task_runners),
vm->GetSettings().task_observer_add,
vm->GetSettings().task_observer_remove,
settings.task_observer_add,
settings.task_observer_remove,
std::move(snapshot_delegate),
std::move(io_manager),
advisory_script_uri,
advisory_script_entrypoint,
vm->GetSettings().log_tag,
vm->GetSettings().unhandled_exception_callback,
vm->GetIsolateNameServer()),
vm_(vm),
settings.log_tag,
settings.unhandled_exception_callback,
DartVMRef::GetIsolateNameServer()),
settings_(settings),
isolate_snapshot_(std::move(isolate_snapshot)),
shared_snapshot_(std::move(shared_snapshot)),
child_isolate_preparer_(std::move(child_isolate_preparer)) {
FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot.";
if (vm_ == nullptr) {
return;
}
phase_ = Phase::Uninitialized;
}
DartIsolate::~DartIsolate() = default;
DartIsolate::Phase DartIsolate::GetPhase() const {
return phase_;
const Settings& DartIsolate::GetSettings() const {
return settings_;
}
DartVM* DartIsolate::GetDartVM() const {
return vm_;
DartIsolate::Phase DartIsolate::GetPhase() const {
return phase_;
}
bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
......@@ -493,16 +489,16 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
const char* package_config,
Dart_IsolateFlags* flags,
char** error) {
auto vm = DartVM::ForProcessIfInitialized();
auto vm_data = DartVMRef::GetVMData();
if (!vm) {
if (!vm_data) {
*error = strdup(
"Could not resolve the VM when attempting to create the service "
"isolate.");
"Could not access VM data to initialize isolates. This may be because "
"the VM has initialized shutdown on another thread already.");
return nullptr;
}
const auto& settings = vm->GetSettings();
const auto& settings = vm_data->GetSettings();
if (!settings.enable_observatory) {
FML_DLOG(INFO) << "Observatory is disabled.";
......@@ -515,21 +511,26 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
flags->load_vmservice_library = true;
if (advisory_script_uri == nullptr) {
advisory_script_uri = "";
}
if (advisory_script_entrypoint == nullptr) {
advisory_script_entrypoint = "";
}
std::weak_ptr<DartIsolate> weak_service_isolate =
DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
vm->GetSharedSnapshot(), // shared snapshot
null_task_runners, // task runners
nullptr, // window
{}, // snapshot delegate
{}, // IO Manager
advisory_script_uri == nullptr ? ""
: advisory_script_uri, // script uri
advisory_script_entrypoint == nullptr
? ""
: advisory_script_entrypoint, // script entrypoint
flags // flags
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // service isolate snapshot
vm_data->GetSharedSnapshot(), // shared snapshot
null_task_runners, // service isolate task runners
nullptr, // window
{}, // snapshot delegate
{}, // IO Manager
advisory_script_uri, // script uri
advisory_script_entrypoint, // script entrypoint
flags // flags
);
std::shared_ptr<DartIsolate> service_isolate = weak_service_isolate.lock();
......@@ -552,7 +553,13 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
return nullptr;
}
vm->GetServiceProtocol().ToggleHooks(true);
if (auto service_protocol = DartVMRef::GetServiceProtocol()) {
service_protocol->ToggleHooks(true);
} else {
FML_DLOG(ERROR)
<< "Could not acquire the service protocol handlers. This might be "
"because the VM has already begun teardown on another thread.";
}
return service_isolate->isolate();
}
......@@ -610,16 +617,13 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
std::unique_ptr<std::shared_ptr<DartIsolate>> embedder_isolate(
p_parent_embedder_isolate);
if (embedder_isolate == nullptr ||
(*embedder_isolate)->GetDartVM() == nullptr) {
if (embedder_isolate == nullptr) {
*error =
strdup("Parent isolate did not have embedder specific callback data.");
FML_DLOG(ERROR) << *error;
return {nullptr, {}};
}
DartVM* const vm = (*embedder_isolate)->GetDartVM();
if (!is_root_isolate) {
auto* raw_embedder_isolate = embedder_isolate.release();
......@@ -628,7 +632,7 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
embedder_isolate = std::make_unique<std::shared_ptr<DartIsolate>>(
std::make_shared<DartIsolate>(
vm, // vm
(*raw_embedder_isolate)->GetSettings(), // settings
(*raw_embedder_isolate)->GetIsolateSnapshot(), // isolate_snapshot
(*raw_embedder_isolate)->GetSharedSnapshot(), // shared_snapshot
null_task_runners, // task_runners
......@@ -701,11 +705,11 @@ void DartIsolate::DartIsolateCleanupCallback(
delete embedder_isolate;
}
fml::RefPtr<DartSnapshot> DartIsolate::GetIsolateSnapshot() const {
fml::RefPtr<const DartSnapshot> DartIsolate::GetIsolateSnapshot() const {
return isolate_snapshot_;
}
fml::RefPtr<DartSnapshot> DartIsolate::GetSharedSnapshot() const {
fml::RefPtr<const DartSnapshot> DartIsolate::GetSharedSnapshot() const {
return shared_snapshot_;
}
......
......@@ -41,9 +41,9 @@ class DartIsolate : public UIDartState {
// bindings. From the VM's perspective, this isolate is not special in any
// way.
static std::weak_ptr<DartIsolate> CreateRootIsolate(
DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
......@@ -52,9 +52,9 @@ class DartIsolate : public UIDartState {
std::string advisory_script_entrypoint,
Dart_IsolateFlags* flags = nullptr);
DartIsolate(DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
DartIsolate(const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
......@@ -64,6 +64,8 @@ class DartIsolate : public UIDartState {
~DartIsolate() override;
const Settings& GetSettings() const;
Phase GetPhase() const;
FML_WARN_UNUSED_RESULT
......@@ -85,11 +87,9 @@ class DartIsolate : public UIDartState {
void AddIsolateShutdownCallback(fml::closure closure);
DartVM* GetDartVM() const;
fml::RefPtr<DartSnapshot> GetIsolateSnapshot() const;
fml::RefPtr<const DartSnapshot> GetIsolateSnapshot() const;
fml::RefPtr<DartSnapshot> GetSharedSnapshot() const;
fml::RefPtr<const DartSnapshot> GetSharedSnapshot() const;
std::weak_ptr<DartIsolate> GetWeakIsolatePtr();
......@@ -108,10 +108,10 @@ class DartIsolate : public UIDartState {
};
friend class DartVM;
DartVM* const vm_ = nullptr;
Phase phase_ = Phase::Unknown;
const fml::RefPtr<DartSnapshot> isolate_snapshot_;
const fml::RefPtr<DartSnapshot> shared_snapshot_;
const Settings settings_;
const fml::RefPtr<const DartSnapshot> isolate_snapshot_;
const fml::RefPtr<const DartSnapshot> shared_snapshot_;
std::vector<std::shared_ptr<const fml::Mapping>> kernel_buffers_;
std::vector<std::unique_ptr<AutoFireClosure>> shutdown_callbacks_;
ChildIsolatePreparer child_isolate_preparer_ = nullptr;
......
......@@ -7,15 +7,11 @@
#include "flutter/fml/thread.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/testing/testing.h"
#include "flutter/testing/thread_test.h"
#include "third_party/tonic/scopes/dart_isolate_scope.h"
#define CURRENT_TEST_NAME \
std::string { \
::testing::UnitTest::GetInstance()->current_test_info()->name() \
}
namespace blink {
using DartIsolateTest = ::testing::ThreadTest;
......@@ -24,24 +20,26 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) {
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto vm = DartVM::ForProcess(settings);
auto vm = DartVMRef::Create(settings);
ASSERT_TRUE(vm);
TaskRunners task_runners(CURRENT_TEST_NAME, //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner() //
auto vm_data = vm->GetVMData();
ASSERT_TRUE(vm_data);
TaskRunners task_runners(testing::GetCurrentTestName(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner() //
);
auto weak_isolate = DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
vm_data->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
);
auto root_isolate = weak_isolate.lock();
ASSERT_TRUE(root_isolate);
......@@ -53,24 +51,26 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto vm = DartVM::ForProcess(settings);
auto vm = DartVMRef::Create(settings);
ASSERT_TRUE(vm);
TaskRunners task_runners(CURRENT_TEST_NAME, //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner() //
auto vm_data = vm->GetVMData();
ASSERT_TRUE(vm_data);
TaskRunners task_runners(testing::GetCurrentTestName(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner(), //
GetCurrentTaskRunner() //
);
auto weak_isolate = DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
vm_data->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
);
auto root_isolate = weak_isolate.lock();
ASSERT_TRUE(root_isolate);
......@@ -86,8 +86,11 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
class AutoIsolateShutdown {
public:
AutoIsolateShutdown(std::shared_ptr<blink::DartIsolate> isolate)
: isolate_(std::move(isolate)) {}
AutoIsolateShutdown(blink::DartVMRef vm,
std::shared_ptr<blink::DartIsolate> isolate)
: vm_(std::move(vm)), isolate_(std::move(isolate)) {
FML_CHECK(vm_);
}
~AutoIsolateShutdown() {
if (isolate_) {
......@@ -119,6 +122,7 @@ class AutoIsolateShutdown {
}
private:
blink::DartVMRef vm_;
std::shared_ptr<blink::DartIsolate> isolate_;
FML_DISALLOW_COPY_AND_ASSIGN(AutoIsolateShutdown);
......@@ -128,35 +132,38 @@ std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
fml::RefPtr<fml::TaskRunner> task_runner,
std::string entrypoint) {
Settings settings = {};
settings.enable_observatory = true;
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto vm = DartVM::ForProcess(settings);
auto vm = DartVMRef::Create(settings);
if (!vm) {
return {};
}
TaskRunners task_runners(CURRENT_TEST_NAME, //
task_runner, //
task_runner, //
task_runner, //
task_runner //
auto vm_data = vm->GetVMData();
TaskRunners task_runners(testing::GetCurrentTestName(), //
task_runner, //
task_runner, //
task_runner, //
task_runner //
);
auto weak_isolate = DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
vm_data->GetSettings(), // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
vm_data->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
);
auto root_isolate =
std::make_unique<AutoIsolateShutdown>(weak_isolate.lock());
std::make_unique<AutoIsolateShutdown>(std::move(vm), weak_isolate.lock());
if (!root_isolate->IsValid()) {
FML_LOG(ERROR) << "Could not create isolate.";
......
......@@ -15,6 +15,7 @@
#include "flutter/fml/file.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/synchronization/thread_annotations.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/trace_event.h"
#include "flutter/lib/io/dart_io.h"
......@@ -239,66 +240,48 @@ static void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
info->name = "Flutter";
}
fml::RefPtr<DartVM> DartVM::ForProcess(Settings settings) {
return ForProcess(settings, nullptr, nullptr, nullptr);
}
static std::once_flag gVMInitialization;
static std::mutex gVMMutex;
static fml::RefPtr<DartVM> gVM;
fml::RefPtr<DartVM> DartVM::ForProcess(
std::shared_ptr<DartVM> DartVM::Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot) {
std::lock_guard<std::mutex> lock(gVMMutex);
std::call_once(gVMInitialization, [settings, //
vm_snapshot, //
isolate_snapshot, //
shared_snapshot //
]() mutable {
if (!vm_snapshot) {
vm_snapshot = DartSnapshot::VMSnapshotFromSettings(settings);
}
if (!(vm_snapshot && vm_snapshot->IsValid())) {
FML_LOG(ERROR) << "VM snapshot must be valid.";
return;
}
if (!isolate_snapshot) {
isolate_snapshot = DartSnapshot::IsolateSnapshotFromSettings(settings);
}
if (!(isolate_snapshot && isolate_snapshot->IsValid())) {
FML_LOG(ERROR) << "Isolate snapshot must be valid.";
return;
}
if (!shared_snapshot) {
shared_snapshot = DartSnapshot::Empty();
}
gVM = fml::MakeRefCounted<DartVM>(settings, //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
std::move(shared_snapshot) //
);
});
return gVM;
fml::RefPtr<DartSnapshot> shared_snapshot,
std::shared_ptr<IsolateNameServer> isolate_name_server) {
auto vm_data = DartVMData::Create(settings, //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
std::move(shared_snapshot) //
);
if (!vm_data) {
FML_LOG(ERROR) << "Could not setup VM data to bootstrap the VM from.";
return {};
}
// Note: std::make_shared unviable due to hidden constructor.
return std::shared_ptr<DartVM>(
new DartVM(std::move(vm_data), std::move(isolate_name_server)));
}
fml::RefPtr<DartVM> DartVM::ForProcessIfInitialized() {
std::lock_guard<std::mutex> lock(gVMMutex);
return gVM;
static std::atomic_size_t gVMLaunchCount;
size_t DartVM::GetVMLaunchCount() {
return gVMLaunchCount;
}
DartVM::DartVM(const Settings& settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot)
: settings_(settings),
vm_snapshot_(std::move(vm_snapshot)),
isolate_snapshot_(std::move(isolate_snapshot)),
shared_snapshot_(std::move(shared_snapshot)),
weak_factory_(this) {
DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
std::shared_ptr<IsolateNameServer> isolate_name_server)
: settings_(vm_data->GetSettings()),
vm_data_(vm_data),
isolate_name_server_(std::move(isolate_name_server)),
service_protocol_(std::make_shared<ServiceProtocol>()) {
TRACE_EVENT0("flutter", "DartVMInitializer");
gVMLaunchCount++;
FML_DCHECK(vm_data_);
FML_DCHECK(isolate_name_server_);
FML_DCHECK(service_protocol_);
FML_DLOG(INFO) << "Attempting Dart VM launch for mode: "
<< (IsRunningPrecompiledCode() ? "AOT" : "Interpreter");
......@@ -306,8 +289,8 @@ DartVM::DartVM(const Settings& settings,
TRACE_EVENT0("flutter", "dart::bin::BootstrapDartIo");
dart::bin::BootstrapDartIo();
if (!settings.temp_directory_path.empty()) {
dart::bin::SetSystemTempDirectory(settings.temp_directory_path.c_str());
if (!settings_.temp_directory_path.empty()) {
dart::bin::SetSystemTempDirectory(settings_.temp_directory_path.c_str());
}
}
......@@ -320,7 +303,7 @@ DartVM::DartVM(const Settings& settings,
args.push_back("--ignore-unrecognized-flags");
for (auto* const profiler_flag :
ProfilingFlags(settings.enable_dart_profiling)) {
ProfilingFlags(settings_.enable_dart_profiling)) {
args.push_back(profiler_flag);
}
......@@ -333,7 +316,7 @@ DartVM::DartVM(const Settings& settings,
// Enable Dart assertions if we are not running precompiled code. We run non-
// precompiled code only in the debug product mode.
bool enable_asserts = !settings.disable_dart_asserts;
bool enable_asserts = !settings_.disable_dart_asserts;
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DYNAMIC_PROFILE || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
......@@ -357,24 +340,24 @@ DartVM::DartVM(const Settings& settings,
PushBackAll(&args, kDartAssertArgs, arraysize(kDartAssertArgs));
}
if (settings.start_paused) {
if (settings_.start_paused) {
PushBackAll(&args, kDartStartPausedArgs, arraysize(kDartStartPausedArgs));
}
if (settings.endless_trace_buffer || settings.trace_startup) {
if (settings_.endless_trace_buffer || settings_.trace_startup) {
// If we are tracing startup, make sure the trace buffer is endless so we
// don't lose early traces.
PushBackAll(&args, kDartEndlessTraceBufferArgs,
arraysize(kDartEndlessTraceBufferArgs));
}
if (settings.trace_systrace) {
if (settings_.trace_systrace) {
PushBackAll(&args, kDartSystraceTraceBufferArgs,
arraysize(kDartSystraceTraceBufferArgs));
PushBackAll(&args, kDartTraceStreamsArgs, arraysize(kDartTraceStreamsArgs));
}
if (settings.trace_startup) {
if (settings_.trace_startup) {
PushBackAll(&args, kDartTraceStartupArgs, arraysize(kDartTraceStartupArgs));
}
......@@ -383,8 +366,8 @@ DartVM::DartVM(const Settings& settings,
PushBackAll(&args, kDartTraceStreamsArgs, arraysize(kDartTraceStreamsArgs));
#endif
for (size_t i = 0; i < settings.dart_flags.size(); i++)
args.push_back(settings.dart_flags[i].c_str());
for (size_t i = 0; i < settings_.dart_flags.size(); i++)
args.push_back(settings_.dart_flags[i].c_str());
char* flags_error = Dart_SetVMFlags(args.size(), args.data());
if (flags_error) {
......@@ -394,14 +377,14 @@ DartVM::DartVM(const Settings& settings,
DartUI::InitForGlobal();
Dart_SetFileModifiedCallback(&DartFileModifiedCallback);
{
TRACE_EVENT0("flutter", "Dart_Initialize");
Dart_InitializeParams params = {};
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
params.vm_snapshot_data = vm_snapshot_->GetData()->GetSnapshotPointer();
params.vm_snapshot_instructions = vm_snapshot_->GetInstructionsIfPresent();
params.vm_snapshot_data =
vm_data_->GetVMSnapshot().GetData()->GetSnapshotPointer();
params.vm_snapshot_instructions =
vm_data_->GetVMSnapshot().GetInstructionsIfPresent();
params.create = reinterpret_cast<decltype(params.create)>(
DartIsolate::DartIsolateCreateCallback);
params.shutdown = reinterpret_cast<decltype(params.shutdown)>(
......@@ -433,51 +416,50 @@ DartVM::DartVM(const Settings& settings,
}
}
Dart_SetFileModifiedCallback(&DartFileModifiedCallback);
// Allow streaming of stdout and stderr by the Dart vm.
Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
&ServiceStreamCancelCallback);
Dart_SetEmbedderInformationCallback(&EmbedderInformationCallback);
FML_DLOG(INFO) << "New Dart VM instance created. Instance count: "
<< gVMLaunchCount;
}
DartVM::~DartVM() {
if (Dart_CurrentIsolate() != nullptr) {
Dart_ExitIsolate();
}
char* result = Dart_Cleanup();
if (result != nullptr) {
FML_LOG(ERROR) << "Could not cleanly shut down the Dart VM. Message: \""
<< result << "\".";
free(result);
}
}
const Settings& DartVM::GetSettings() const {
return settings_;
}
dart::bin::CleanupDartIo();
const DartSnapshot& DartVM::GetVMSnapshot() const {
return *vm_snapshot_.get();
}
FML_CHECK(result == nullptr)
<< "Could not cleanly shut down the Dart VM. Error: \"" << result
<< "\".";
free(result);
IsolateNameServer* DartVM::GetIsolateNameServer() {
return &isolate_name_server_;
FML_DLOG(INFO) << "Dart VM instance destroyed. Instance count: "
<< gVMLaunchCount;
}
fml::RefPtr<DartSnapshot> DartVM::GetIsolateSnapshot() const {
return isolate_snapshot_;
std::shared_ptr<const DartVMData> DartVM::GetVMData() const {
return vm_data_;
}
fml::RefPtr<DartSnapshot> DartVM::GetSharedSnapshot() const {
return shared_snapshot_;
const Settings& DartVM::GetSettings() const {
return settings_;
}
ServiceProtocol& DartVM::GetServiceProtocol() {
std::shared_ptr<ServiceProtocol> DartVM::GetServiceProtocol() const {
return service_protocol_;
}
fml::WeakPtr<DartVM> DartVM::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
std::shared_ptr<IsolateNameServer> DartVM::GetIsolateNameServer() const {
return isolate_name_server_;
}
} // namespace blink
......@@ -5,9 +5,8 @@
#ifndef FLUTTER_RUNTIME_DART_VM_H_
#define FLUTTER_RUNTIME_DART_VM_H_
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include "flutter/common/settings.h"
#include "flutter/fml/build_config.h"
......@@ -19,59 +18,48 @@
#include "flutter/lib/ui/isolate_name_server/isolate_name_server.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_snapshot.h"
#include "flutter/runtime/dart_vm_data.h"
#include "flutter/runtime/service_protocol.h"
#include "third_party/dart/runtime/include/dart_api.h"
namespace blink {
class DartVM : public fml::RefCountedThreadSafe<DartVM> {
class DartVM {
public:
static fml::RefPtr<DartVM> ForProcess(Settings settings);
static fml::RefPtr<DartVM> ForProcess(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot);
static fml::RefPtr<DartVM> ForProcessIfInitialized();
~DartVM();
static bool IsRunningPrecompiledCode();
static bool IsKernelMapping(const fml::FileMapping* mapping);
const Settings& GetSettings() const;
const DartSnapshot& GetVMSnapshot() const;
static size_t GetVMLaunchCount();
IsolateNameServer* GetIsolateNameServer();
fml::RefPtr<DartSnapshot> GetIsolateSnapshot() const;
const Settings& GetSettings() const;
fml::RefPtr<DartSnapshot> GetSharedSnapshot() const;
std::shared_ptr<const DartVMData> GetVMData() const;
fml::WeakPtr<DartVM> GetWeakPtr();
std::shared_ptr<ServiceProtocol> GetServiceProtocol() const;
ServiceProtocol& GetServiceProtocol();
std::shared_ptr<IsolateNameServer> GetIsolateNameServer() const;
private:
const Settings settings_;
const fml::RefPtr<DartSnapshot> vm_snapshot_;
IsolateNameServer isolate_name_server_;
const fml::RefPtr<DartSnapshot> isolate_snapshot_;
const fml::RefPtr<DartSnapshot> shared_snapshot_;
ServiceProtocol service_protocol_;
fml::WeakPtrFactory<DartVM> weak_factory_;
DartVM(const Settings& settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot);
std::shared_ptr<const DartVMData> vm_data_;
const std::shared_ptr<IsolateNameServer> isolate_name_server_;
const std::shared_ptr<ServiceProtocol> service_protocol_;
~DartVM();
friend class DartVMRef;
static std::shared_ptr<DartVM> Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
std::shared_ptr<IsolateNameServer> isolate_name_server);
DartVM(std::shared_ptr<const DartVMData> data,
std::shared_ptr<IsolateNameServer> isolate_name_server);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(DartVM);
FML_FRIEND_MAKE_REF_COUNTED(DartVM);
FML_DISALLOW_COPY_AND_ASSIGN(DartVM);
};
......
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/runtime/dart_vm_data.h"
namespace blink {
std::shared_ptr<const DartVMData> DartVMData::Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot) {
if (!vm_snapshot || !vm_snapshot->IsValid()) {
// Caller did not provide a valid VM snapshot. Attempt to infer one
// from the settings.
vm_snapshot = DartSnapshot::VMSnapshotFromSettings(settings);
if (!vm_snapshot) {
FML_LOG(ERROR)
<< "VM snapshot invalid and could not be inferred from settings.";
return {};
}
}
if (!isolate_snapshot || !isolate_snapshot->IsValid()) {
// Caller did not provide a valid isolate snapshot. Attempt to infer one
// from the settings.
isolate_snapshot = DartSnapshot::IsolateSnapshotFromSettings(settings);
if (!isolate_snapshot) {
FML_LOG(ERROR) << "Isolate snapshot invalid and could not be inferred "
"from settings.";
return {};
}
}
if (!shared_snapshot || !shared_snapshot->IsValid()) {
shared_snapshot = DartSnapshot::Empty();
if (!shared_snapshot) {
FML_LOG(ERROR) << "Shared snapshot invalid.";
return {};
}
}
return std::shared_ptr<const DartVMData>(new DartVMData(
std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
std::move(shared_snapshot) //
));
}
DartVMData::DartVMData(Settings settings,
fml::RefPtr<const DartSnapshot> vm_snapshot,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot)
: settings_(settings),
vm_snapshot_(vm_snapshot),
isolate_snapshot_(isolate_snapshot),
shared_snapshot_(shared_snapshot) {}
DartVMData::~DartVMData() = default;
const Settings& DartVMData::GetSettings() const {
return settings_;
}
const DartSnapshot& DartVMData::GetVMSnapshot() const {
return *vm_snapshot_;
}
fml::RefPtr<const DartSnapshot> DartVMData::GetIsolateSnapshot() const {
return isolate_snapshot_;
}
fml::RefPtr<const DartSnapshot> DartVMData::GetSharedSnapshot() const {
return shared_snapshot_;
}
} // namespace blink
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_RUNTIME_DART_VM_DATA_H_
#define FLUTTER_RUNTIME_DART_VM_DATA_H_
#include "flutter/fml/macros.h"
#include "flutter/runtime/dart_snapshot.h"
namespace blink {
class DartVMData {
public:
static std::shared_ptr<const DartVMData> Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot);
~DartVMData();
const Settings& GetSettings() const;
const DartSnapshot& GetVMSnapshot() const;
fml::RefPtr<const DartSnapshot> GetIsolateSnapshot() const;
fml::RefPtr<const DartSnapshot> GetSharedSnapshot() const;
private:
const Settings settings_;
const fml::RefPtr<const DartSnapshot> vm_snapshot_;
const fml::RefPtr<const DartSnapshot> isolate_snapshot_;
const fml::RefPtr<const DartSnapshot> shared_snapshot_;
DartVMData(Settings settings,
fml::RefPtr<const DartSnapshot> vm_snapshot,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot);
FML_DISALLOW_COPY_AND_ASSIGN(DartVMData);
};
} // namespace blink
#endif // FLUTTER_RUNTIME_DART_VM_DATA_H_
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/runtime/dart_vm_lifecycle.h"
#include <mutex>
namespace blink {
// We need to explicitly put the constructor and destructor of the DartVM in the
// critical section. All accesses (not just const members) to the global VM
// object weak pointer are behind this mutex.
static std::mutex gVMMutex;
static std::weak_ptr<DartVM> gVM FML_GUARDED_BY(gVMMutex);
// We are going to be modifying more than just the control blocks of the
// following weak pointers (in the |Create| case where an old VM could not be
// reused). Ideally, we would use |std::atomic<std::weak_ptr<T>>| specialization
// but that is only available since C++20. We don't expect contention on these
// locks so we just use one mutex for all.
static std::mutex gVMDependentsMutex;
static std::weak_ptr<const DartVMData> gVMData
FML_GUARDED_BY(gVMDependentsMutex);
static std::weak_ptr<ServiceProtocol> gVMServiceProtocol
FML_GUARDED_BY(gVMDependentsMutex);
static std::weak_ptr<IsolateNameServer> gVMIsolateNameServer
FML_GUARDED_BY(gVMDependentsMutex);
DartVMRef::DartVMRef(std::shared_ptr<DartVM> vm) : vm_(vm) {}
DartVMRef::DartVMRef(DartVMRef&& other) = default;
DartVMRef::~DartVMRef() {
if (!vm_) {
// If there is no valid VM (possible via a move), there is no way that the
// decrement on the shared pointer can cause a collection. Avoid acquiring
// the lifecycle lock in this case. This is just working around a
// pessimization and not required for correctness.
return;
}
std::lock_guard<std::mutex> lifecycle_lock(gVMMutex);
vm_.reset();
}
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot) {
std::lock_guard<std::mutex> lifecycle_lock(gVMMutex);
// If there is already a running VM in the process, grab a strong reference to
// it.
if (auto vm = gVM.lock()) {
FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
"already running. Ignoring arguments for current VM "
"create call and reusing the old VM.";
// There was already a running VM in the process,
return DartVMRef{std::move(vm)};
}
std::lock_guard<std::mutex> dependents_lock(gVMDependentsMutex);
gVMData.reset();
gVMServiceProtocol.reset();
gVMIsolateNameServer.reset();
gVM.reset();
// If there is no VM in the process. Initialize one, hold the weak reference
// and pass a strong reference to the caller.
auto isolate_name_server = std::make_shared<IsolateNameServer>();
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
isolate_name_server //
);
if (!vm) {
FML_LOG(ERROR) << "Could not create Dart VM instance.";
return {nullptr};
}
gVMData = vm->GetVMData();
gVMServiceProtocol = vm->GetServiceProtocol();
gVMIsolateNameServer = isolate_name_server;
gVM = vm;
return DartVMRef{std::move(vm)};
}
bool DartVMRef::IsInstanceRunning() {
std::lock_guard<std::mutex> lock(gVMMutex);
return !gVM.expired();
}
std::shared_ptr<const DartVMData> DartVMRef::GetVMData() {
std::lock_guard<std::mutex> lock(gVMDependentsMutex);
return gVMData.lock();
}
std::shared_ptr<ServiceProtocol> DartVMRef::GetServiceProtocol() {
std::lock_guard<std::mutex> lock(gVMDependentsMutex);
return gVMServiceProtocol.lock();
}
std::shared_ptr<IsolateNameServer> DartVMRef::GetIsolateNameServer() {
std::lock_guard<std::mutex> lock(gVMDependentsMutex);
return gVMIsolateNameServer.lock();
}
} // namespace blink
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_RUNTIME_DART_VM_LIFECYCLE_H_
#define FLUTTER_RUNTIME_DART_VM_LIFECYCLE_H_
#include <memory>
#include "flutter/fml/macros.h"
#include "flutter/lib/ui/isolate_name_server/isolate_name_server.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/service_protocol.h"
namespace blink {
// A strong reference to the Dart VM. There can only be one VM running in the
// process at any given time. A reference to the VM may only be obtained via the
// |Create| method. In case there is already a running instance of the VM in the
// process, a strong reference to that VM is obtained and the arguments to the
// |Create| call ignored. If there is no VM already running in the process, a VM
// is initialized in a thread safe manner and returned to the caller. The VM
// will shutdown only when all callers relinquish their references (by
// collecting their instances of this class).
//
// DartVMRef instances may be created on any thread.
class DartVMRef {
public:
FML_WARN_UNUSED_RESULT
static DartVMRef Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot = nullptr,
fml::RefPtr<DartSnapshot> isolate_snapshot = nullptr,
fml::RefPtr<DartSnapshot> shared_snapshot = nullptr);
DartVMRef(DartVMRef&&);
~DartVMRef();
// This is an inherently racy way to check if a VM instance is running and
// should not be used outside of unit-tests where there is a known threading
// model.
static bool IsInstanceRunning();
static std::shared_ptr<const DartVMData> GetVMData();
static std::shared_ptr<ServiceProtocol> GetServiceProtocol();
static std::shared_ptr<IsolateNameServer> GetIsolateNameServer();
operator bool() const { return static_cast<bool>(vm_); }
DartVM* operator->() {
FML_DCHECK(vm_);
return vm_.get();
}
DartVM* operator&() {
FML_DCHECK(vm_);
return vm_.get();
}
private:
std::shared_ptr<DartVM> vm_;
DartVMRef(std::shared_ptr<DartVM> vm);
FML_DISALLOW_COPY_AND_ASSIGN(DartVMRef);
};
} // namespace blink
#endif // FLUTTER_RUNTIME_DART_VM_LIFECYCLE_H_
......@@ -3,25 +3,36 @@
// found in the LICENSE file.
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/testing/testing.h"
#include "flutter/testing/thread_test.h"
#include "gtest/gtest.h"
namespace blink {
TEST(DartVM, SimpleInitialization) {
Settings settings = {};
static Settings GetTestSettings() {
Settings settings;
settings.verbose_logging = true;
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto vm = DartVM::ForProcess(settings);
ASSERT_TRUE(vm);
ASSERT_EQ(vm, DartVM::ForProcess(settings));
return settings;
}
TEST(DartVM, SimpleInitialization) {
auto vm1 = DartVMRef::Create(GetTestSettings());
ASSERT_TRUE(vm1);
// Multiple initializations should return the same VM.
auto vm2 = DartVMRef::Create(GetTestSettings());
ASSERT_TRUE(vm2);
ASSERT_EQ(&vm1, &vm2);
ASSERT_FALSE(DartVM::IsRunningPrecompiledCode());
}
TEST(DartVM, SimpleIsolateNameServer) {
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto vm = DartVM::ForProcess(settings);
auto vm = DartVMRef::Create(GetTestSettings());
auto ns = vm->GetIsolateNameServer();
ASSERT_EQ(ns->LookupIsolatePortByName("foobar"), ILLEGAL_PORT);
ASSERT_FALSE(ns->RemoveIsolateNameMapping("foobar"));
......@@ -31,4 +42,79 @@ TEST(DartVM, SimpleIsolateNameServer) {
ASSERT_TRUE(ns->RemoveIsolateNameMapping("foobar"));
}
TEST(DartVM, CanReinitializeVMOverAndOver) {
size_t vm_launch_count = DartVM::GetVMLaunchCount();
for (size_t i = 0; i < 1000; ++i) {
FML_LOG(INFO) << "Run " << i + 1;
// VM should not already be running.
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
auto vm = DartVMRef::Create(GetTestSettings());
ASSERT_TRUE(vm);
size_t new_vm_launch_count = DartVM::GetVMLaunchCount();
ASSERT_EQ(vm_launch_count + 1, new_vm_launch_count);
vm_launch_count = new_vm_launch_count;
// VM should now be running
ASSERT_TRUE(DartVMRef::IsInstanceRunning());
}
}
using DartVMThreadTest = ::testing::ThreadTest;
TEST_F(DartVMThreadTest, CanRunIsolatesInANewVM) {
for (size_t i = 0; i < 1000; ++i) {
FML_LOG(INFO) << "Run " << i + 1;
size_t vm_launch_count = DartVM::GetVMLaunchCount();
// VM should not already be running.
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
auto vm = DartVMRef::Create(GetTestSettings());
ASSERT_TRUE(vm);
// VM should not already be running.
ASSERT_TRUE(DartVMRef::IsInstanceRunning());
size_t new_vm_launch_count = DartVM::GetVMLaunchCount();
ASSERT_EQ(vm_launch_count + 1, new_vm_launch_count);
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};
auto labels = testing::GetCurrentTestName() + std::to_string(i);
shell::ThreadHost host(labels, shell::ThreadHost::Type::UI |
shell::ThreadHost::Type::GPU |
shell::ThreadHost::Type::IO);
TaskRunners task_runners(
labels, // task runner labels
GetCurrentTaskRunner(), // platform task runner
host.gpu_thread->GetTaskRunner(), // GPU task runner
host.ui_thread->GetTaskRunner(), // UI task runner
host.io_thread->GetTaskRunner() // IO task runner
);
auto weak_isolate = DartIsolate::CreateRootIsolate(
vm->GetVMData()->GetSettings(), // settings
vm->GetVMData()->GetIsolateSnapshot(), // isolate snapshot
vm->GetVMData()->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
);
auto root_isolate = weak_isolate.lock();
ASSERT_TRUE(root_isolate);
ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::LibrariesSetup);
ASSERT_TRUE(root_isolate->Shutdown());
}
}
} // namespace blink
......@@ -17,8 +17,8 @@ namespace blink {
RuntimeController::RuntimeController(
RuntimeDelegate& p_client,
DartVM* p_vm,
fml::RefPtr<DartSnapshot> p_isolate_snapshot,
fml::RefPtr<DartSnapshot> p_shared_snapshot,
fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
fml::RefPtr<const DartSnapshot> p_shared_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<IOManager> p_io_manager,
......@@ -40,8 +40,8 @@ RuntimeController::RuntimeController(
RuntimeController::RuntimeController(
RuntimeDelegate& p_client,
DartVM* p_vm,
fml::RefPtr<DartSnapshot> p_isolate_snapshot,
fml::RefPtr<DartSnapshot> p_shared_snapshot,
fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
fml::RefPtr<const DartSnapshot> p_shared_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<IOManager> p_io_manager,
......@@ -61,7 +61,7 @@ RuntimeController::RuntimeController(
idle_notification_callback_(idle_notification_callback),
window_data_(std::move(p_window_data)),
root_isolate_(
DartIsolate::CreateRootIsolate(vm_,
DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(),
isolate_snapshot_,
shared_snapshot_,
task_runners_,
......
......@@ -30,8 +30,8 @@ class RuntimeController final : public WindowClient {
public:
RuntimeController(RuntimeDelegate& client,
DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
......@@ -118,8 +118,8 @@ class RuntimeController final : public WindowClient {
RuntimeDelegate& client_;
DartVM* const vm_;
fml::RefPtr<DartSnapshot> isolate_snapshot_;
fml::RefPtr<DartSnapshot> shared_snapshot_;
fml::RefPtr<const DartSnapshot> isolate_snapshot_;
fml::RefPtr<const DartSnapshot> shared_snapshot_;
TaskRunners task_runners_;
fml::WeakPtr<SnapshotDelegate> snapshot_delegate_;
fml::WeakPtr<IOManager> io_manager_;
......@@ -132,8 +132,8 @@ class RuntimeController final : public WindowClient {
RuntimeController(RuntimeDelegate& client,
DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
......
......@@ -37,8 +37,8 @@ static constexpr char kSettingsChannel[] = "flutter/settings";
Engine::Engine(Delegate& delegate,
blink::DartVM& vm,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
blink::TaskRunners task_runners,
blink::Settings settings,
std::unique_ptr<Animator> animator,
......
......@@ -56,8 +56,8 @@ class Engine final : public blink::RuntimeDelegate {
Engine(Delegate& delegate,
blink::DartVM& vm,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
blink::TaskRunners task_runners,
blink::Settings settings,
std::unique_ptr<Animator> animator,
......
......@@ -36,17 +36,20 @@ namespace shell {
constexpr char kSkiaChannel[] = "flutter/skia";
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
blink::DartVMRef vm,
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
if (!task_runners.IsValid()) {
FML_LOG(ERROR) << "Task runners to run the shell were invalid.";
return nullptr;
}
auto shell = std::unique_ptr<Shell>(new Shell(task_runners, settings));
auto shell =
std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
......@@ -75,6 +78,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
&platform_view, //
io_task_runner //
]() {
TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
io_manager = std::make_unique<IOManager>(
platform_view->CreateResourceContext(), io_task_runner);
io_latch.Signal();
......@@ -92,6 +96,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
shell = shell.get(), //
&snapshot_delegate //
]() {
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
if (auto new_rasterizer = on_create_rasterizer(*shell)) {
rasterizer = std::move(new_rasterizer);
snapshot_delegate = rasterizer->GetSnapshotDelegate();
......@@ -115,6 +120,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
snapshot_delegate = std::move(snapshot_delegate), //
io_manager = io_manager->GetWeakPtr() //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();
// The animator is owned by the UI thread but it gets its vsync pulses
......@@ -123,7 +129,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
std::move(vsync_waiter));
engine = std::make_unique<Engine>(*shell, //
shell->GetDartVM(), //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
task_runners, //
......@@ -204,26 +210,35 @@ std::unique_ptr<Shell> Shell::Create(
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
auto vm = blink::DartVM::ForProcess(settings);
TRACE_EVENT0("flutter", "Shell::Create");
auto vm = blink::DartVMRef::Create(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";
auto vm_data = vm->GetVMData();
return Shell::Create(std::move(task_runners), //
std::move(settings), //
vm->GetIsolateSnapshot(), //
blink::DartSnapshot::Empty(), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
blink::DartSnapshot::Empty(), // shared snapshot
std::move(on_create_platform_view), //
std::move(on_create_rasterizer) //
std::move(on_create_rasterizer), //
std::move(vm) //
);
}
std::unique_ptr<Shell> Shell::Create(
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
blink::DartVMRef vm) {
PerformInitializationTasks(settings);
TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots");
if (!task_runners.IsValid() || !on_create_platform_view ||
!on_create_rasterizer) {
return nullptr;
......@@ -233,16 +248,18 @@ std::unique_ptr<Shell> Shell::Create(
std::unique_ptr<Shell> shell;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(),
[&latch, //
&shell, //
task_runners = std::move(task_runners), //
settings, //
isolate_snapshot = std::move(isolate_snapshot), //
shared_snapshot = std::move(shared_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
]() {
shell = CreateShellOnPlatformThread(std::move(task_runners), //
fml::MakeCopyable([&latch, //
vm = std::move(vm), //
&shell, //
task_runners = std::move(task_runners), //
settings, //
isolate_snapshot = std::move(isolate_snapshot), //
shared_snapshot = std::move(shared_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
]() mutable {
shell = CreateShellOnPlatformThread(std::move(vm),
std::move(task_runners), //
settings, //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
......@@ -250,15 +267,18 @@ std::unique_ptr<Shell> Shell::Create(
on_create_rasterizer //
);
latch.Signal();
});
}));
latch.Wait();
return shell;
}
Shell::Shell(blink::TaskRunners task_runners, blink::Settings settings)
Shell::Shell(blink::DartVMRef vm,
blink::TaskRunners task_runners,
blink::Settings settings)
: task_runners_(std::move(task_runners)),
settings_(std::move(settings)),
vm_(blink::DartVM::ForProcess(settings_)) {
vm_(std::move(vm)) {
FML_CHECK(vm_) << "Must have access to VM to create a shell.";
FML_DCHECK(task_runners_.IsValid());
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
......@@ -300,9 +320,7 @@ Shell::~Shell() {
PersistentCache::GetCacheForProcess()->RemoveWorkerTaskRunner(
task_runners_.GetIOTaskRunner());
if (auto vm = blink::DartVM::ForProcessIfInitialized()) {
vm->GetServiceProtocol().RemoveHandler(this);
}
vm_->GetServiceProtocol()->RemoveHandler(this);
fml::AutoResetWaitableEvent ui_latch, gpu_latch, platform_latch, io_latch;
......@@ -373,9 +391,7 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
is_setup_ = true;
if (auto vm = blink::DartVM::ForProcessIfInitialized()) {
vm->GetServiceProtocol().AddHandler(this, GetServiceProtocolDescription());
}
vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
task_runners_.GetIOTaskRunner());
......@@ -406,12 +422,13 @@ fml::WeakPtr<PlatformView> Shell::GetPlatformView() {
return platform_view_->GetWeakPtr();
}
blink::DartVM& Shell::GetDartVM() const {
return *vm_;
blink::DartVM* Shell::GetDartVM() {
return &vm_;
}
// |shell::PlatformView::Delegate|
void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated");
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
......@@ -469,6 +486,7 @@ void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
// |shell::PlatformView::Delegate|
void Shell::OnPlatformViewDestroyed() {
TRACE_EVENT0("flutter", "Shell::OnPlatformViewDestroyed");
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
......@@ -804,10 +822,8 @@ void Shell::OnPreEngineRestart() {
// |shell::Engine::Delegate|
void Shell::UpdateIsolateDescription(const std::string isolate_name,
int64_t isolate_port) {
if (auto vm = blink::DartVM::ForProcessIfInitialized()) {
Handler::Description description(isolate_port, isolate_name);
vm->GetServiceProtocol().SetHandlerDescription(this, description);
}
Handler::Description description(isolate_port, isolate_name);
vm_->GetServiceProtocol()->SetHandlerDescription(this, description);
}
// |blink::ServiceProtocol::Handler|
......
......@@ -23,6 +23,7 @@
#include "flutter/lib/ui/semantics/custom_accessibility_action.h"
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/runtime/service_protocol.h"
#include "flutter/shell/common/animator.h"
#include "flutter/shell/common/engine.h"
......@@ -54,10 +55,11 @@ class Shell final : public PlatformView::Delegate,
static std::unique_ptr<Shell> Create(
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
CreateCallback<PlatformView> on_create_platform_view,
CreateCallback<Rasterizer> on_create_rasterizer);
CreateCallback<Rasterizer> on_create_rasterizer,
blink::DartVMRef vm);
~Shell();
......@@ -71,7 +73,7 @@ class Shell final : public PlatformView::Delegate,
fml::WeakPtr<PlatformView> GetPlatformView();
blink::DartVM& GetDartVM() const;
blink::DartVM* GetDartVM();
bool IsSetup() const;
......@@ -85,7 +87,7 @@ class Shell final : public PlatformView::Delegate,
const blink::TaskRunners task_runners_;
const blink::Settings settings_;
fml::RefPtr<blink::DartVM> vm_;
blink::DartVMRef vm_;
std::unique_ptr<PlatformView> platform_view_; // on platform task runner
std::unique_ptr<Engine> engine_; // on UI task runner
std::unique_ptr<Rasterizer> rasterizer_; // on GPU task runner
......@@ -98,16 +100,19 @@ class Shell final : public PlatformView::Delegate,
>
service_protocol_handlers_;
bool is_setup_ = false;
uint64_t next_pointer_flow_id_ = 0;
Shell(blink::TaskRunners task_runners, blink::Settings settings);
Shell(blink::DartVMRef vm,
blink::TaskRunners task_runners,
blink::Settings settings);
static std::unique_ptr<Shell> CreateShellOnPlatformThread(
blink::DartVMRef vm,
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<blink::DartSnapshot> shared_snapshot,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer);
......
......@@ -6,6 +6,8 @@
namespace testing {
//
std::string GetCurrentTestName() {
return UnitTest::GetInstance()->current_test_info()->name();
}
} // namespace testing
......@@ -5,6 +5,8 @@
#ifndef TESTING_TESTING_H_
#define TESTING_TESTING_H_
#include <string>
#include "gtest/gtest.h"
namespace testing {
......@@ -14,6 +16,8 @@ namespace testing {
// error.
const char* GetFixturesPath();
std::string GetCurrentTestName();
} // namespace testing
#endif // TESTING_TESTING_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册