From b7d4278b4f293b4782f3faabda3568d5da70db6a Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 10 Dec 2019 10:34:50 -0800 Subject: [PATCH] Create separate objects for isolate state and isolate group state (#14268) Isolate data may need to be deleted on the same thread where it was allocated. In particular, the task observer set up in the UIDartState ctor must be removed from the same message loop where it was added. The engine had been using the same DartIsolate object as the root isolate data and as the isolate group data. This object would be deleted when the isolate group was shut down. However, group shutdown may occur on a thread associated with a secondary isolate. When this happens, cleanup of any state tied to the root isolate's thread will fail. This change adds a DartIsolateGroupData object holding state that is common among all isolates in a group. DartIsolateGroupData can be deleted on any thread. See https://github.com/flutter/flutter/issues/45578 --- ci/licenses_golden/licenses_flutter | 2 + runtime/BUILD.gn | 2 + runtime/dart_isolate.cc | 375 +++++++++++++--------------- runtime/dart_isolate.h | 57 +---- runtime/dart_isolate_group_data.cc | 65 +++++ runtime/dart_isolate_group_data.h | 63 +++++ runtime/dart_isolate_unittests.cc | 17 +- 7 files changed, 321 insertions(+), 260 deletions(-) create mode 100644 runtime/dart_isolate_group_data.cc create mode 100644 runtime/dart_isolate_group_data.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ed92e13fd2a57..bad6d1b797fa5 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -491,6 +491,8 @@ FILE: ../../../flutter/lib/web_ui/lib/ui.dart FILE: ../../../flutter/lib/web_ui/tool/unicode_sync_script.dart FILE: ../../../flutter/runtime/dart_isolate.cc FILE: ../../../flutter/runtime/dart_isolate.h +FILE: ../../../flutter/runtime/dart_isolate_group_data.cc +FILE: ../../../flutter/runtime/dart_isolate_group_data.h FILE: ../../../flutter/runtime/dart_isolate_unittests.cc FILE: ../../../flutter/runtime/dart_lifecycle_unittests.cc FILE: ../../../flutter/runtime/dart_service_isolate.cc diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index 5e41f19f031e2..edd3f8198bcbf 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -46,6 +46,8 @@ source_set("runtime") { sources = [ "dart_isolate.cc", "dart_isolate.h", + "dart_isolate_group_data.cc", + "dart_isolate_group_data.h", "dart_service_isolate.cc", "dart_service_isolate.h", "dart_snapshot.cc", diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 9fe676aca7b5b..97f55a2507961 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -12,6 +12,7 @@ #include "flutter/lib/io/dart_io.h" #include "flutter/lib/ui/dart_runtime_hooks.h" #include "flutter/lib/ui/dart_ui.h" +#include "flutter/runtime/dart_isolate_group_data.h" #include "flutter/runtime/dart_service_isolate.h" #include "flutter/runtime/dart_vm.h" #include "flutter/runtime/dart_vm_lifecycle.h" @@ -29,6 +30,27 @@ namespace flutter { +namespace { + +class DartErrorString { + public: + DartErrorString() : str_(nullptr) {} + ~DartErrorString() { + if (str_) { + ::free(str_); + } + } + char** error() { return &str_; } + const char* str() const { return str_; } + operator bool() const { return str_ != nullptr; } + + private: + FML_DISALLOW_COPY_AND_ASSIGN(DartErrorString); + char* str_; +}; + +} // anonymous namespace + std::weak_ptr DartIsolate::CreateRootIsolate( const Settings& settings, fml::RefPtr isolate_snapshot, @@ -44,21 +66,24 @@ std::weak_ptr DartIsolate::CreateRootIsolate( const fml::closure& isolate_create_callback, const fml::closure& isolate_shutdown_callback) { TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate"); - Dart_Isolate vm_isolate = nullptr; - std::weak_ptr embedder_isolate; - - char* error = nullptr; - // Since this is the root isolate, we fake a parent embedder data object. We - // cannot use unique_ptr here because the destructor is private (since the - // isolate lifecycle is entirely managed by the VM). - // // The child isolate preparer is null but will be set when the isolate is // being prepared to run. - auto root_embedder_data = std::make_unique>( + auto isolate_group_data = + std::make_unique>( + std::shared_ptr(new DartIsolateGroupData( + settings, // settings + std::move(isolate_snapshot), // isolate snapshot + advisory_script_uri, // advisory URI + advisory_script_entrypoint, // advisory entrypoint + nullptr, // child isolate preparer + isolate_create_callback, // isolate create callback + isolate_shutdown_callback // isolate shutdown callback + ))); + + auto isolate_data = std::make_unique>( std::shared_ptr(new DartIsolate( settings, // settings - std::move(isolate_snapshot), // isolate snapshot task_runners, // task runners std::move(snapshot_delegate), // snapshot delegate std::move(io_manager), // IO manager @@ -66,46 +91,31 @@ std::weak_ptr DartIsolate::CreateRootIsolate( std::move(image_decoder), // Image Decoder advisory_script_uri, // advisory URI advisory_script_entrypoint, // advisory entrypoint - nullptr, // child isolate preparer - isolate_create_callback, // isolate create callback - isolate_shutdown_callback, // isolate shutdown callback - true, // is_root_isolate - true // is_group_root_isolate + true // is_root_isolate ))); - std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair( - advisory_script_uri.c_str(), // advisory script URI - advisory_script_entrypoint.c_str(), // advisory script entrypoint - nullptr, // package root - nullptr, // package config - flags, // flags - root_embedder_data.get(), // parent embedder data - true, // is root isolate - &error // error (out) - ); + DartErrorString error; + Dart_Isolate vm_isolate = + CreateDartIsolateGroup(std::move(isolate_group_data), + std::move(isolate_data), flags, error.error()); - if (error != nullptr) { - free(error); + if (error) { + FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << error.str(); } if (vm_isolate == nullptr) { return {}; } - std::shared_ptr shared_embedder_isolate = - embedder_isolate.lock(); - if (shared_embedder_isolate) { - // Only root isolates can interact with windows. - shared_embedder_isolate->SetWindow(std::move(window)); - } + std::shared_ptr* root_isolate_data = + static_cast*>(Dart_IsolateData(vm_isolate)); - root_embedder_data.release(); + (*root_isolate_data)->SetWindow(std::move(window)); - return embedder_isolate; + return (*root_isolate_data)->GetWeakIsolatePtr(); } DartIsolate::DartIsolate(const Settings& settings, - fml::RefPtr isolate_snapshot, TaskRunners task_runners, fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, @@ -113,11 +123,7 @@ DartIsolate::DartIsolate(const Settings& settings, fml::WeakPtr image_decoder, std::string advisory_script_uri, std::string advisory_script_entrypoint, - const ChildIsolatePreparer& child_isolate_preparer, - const fml::closure& isolate_create_callback, - const fml::closure& isolate_shutdown_callback, - bool is_root_isolate, - bool is_group_root_isolate) + bool is_root_isolate) : UIDartState(std::move(task_runners), settings.task_observer_add, settings.task_observer_remove, @@ -130,21 +136,14 @@ DartIsolate::DartIsolate(const Settings& settings, settings.log_tag, settings.unhandled_exception_callback, DartVMRef::GetIsolateNameServer()), - settings_(settings), - isolate_snapshot_(std::move(isolate_snapshot)), - child_isolate_preparer_(std::move(child_isolate_preparer)), - isolate_create_callback_(isolate_create_callback), - isolate_shutdown_callback_(isolate_shutdown_callback), - is_root_isolate_(is_root_isolate), - is_group_root_isolate_(is_group_root_isolate) { - FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot."; + is_root_isolate_(is_root_isolate) { phase_ = Phase::Uninitialized; } -DartIsolate::~DartIsolate() = default; - -const Settings& DartIsolate::GetSettings() const { - return settings_; +DartIsolate::~DartIsolate() { + if (IsRootIsolate() && GetMessageHandlingTaskRunner()) { + FML_DCHECK(GetMessageHandlingTaskRunner()->RunsTasksOnCurrentThread()); + } } DartIsolate::Phase DartIsolate::GetPhase() const { @@ -295,12 +294,14 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() { return false; } - child_isolate_preparer_ = [](DartIsolate* isolate) { + GetIsolateGroupData().SetChildIsolatePreparer([](DartIsolate* isolate) { return isolate->PrepareForRunningFromPrecompiledCode(); - }; + }); - if (isolate_create_callback_) { - isolate_create_callback_(); + const fml::closure& isolate_create_callback = + GetIsolateGroupData().GetIsolateCreateCallback(); + if (isolate_create_callback) { + isolate_create_callback(); } phase_ = Phase::Ready; @@ -376,22 +377,24 @@ bool DartIsolate::PrepareForRunningFromKernel( // Child isolate shares root isolate embedder_isolate (lines 691 and 693 // below). Re-initializing child_isolate_preparer_ lambda while it is being // executed leads to crashes. - if (child_isolate_preparer_ == nullptr) { - child_isolate_preparer_ = [buffers = - kernel_buffers_](DartIsolate* isolate) { - for (unsigned long i = 0; i < buffers.size(); i++) { - bool last_piece = i + 1 == buffers.size(); - const std::shared_ptr& buffer = buffers.at(i); - if (!isolate->PrepareForRunningFromKernel(buffer, last_piece)) { - return false; - } - } - return true; - }; + if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) { + GetIsolateGroupData().SetChildIsolatePreparer( + [buffers = kernel_buffers_](DartIsolate* isolate) { + for (unsigned long i = 0; i < buffers.size(); i++) { + bool last_piece = i + 1 == buffers.size(); + const std::shared_ptr& buffer = buffers.at(i); + if (!isolate->PrepareForRunningFromKernel(buffer, last_piece)) { + return false; + } + } + return true; + }); } - if (isolate_create_callback_) { - isolate_create_callback_(); + const fml::closure& isolate_create_callback = + GetIsolateGroupData().GetIsolateCreateCallback(); + if (isolate_create_callback) { + isolate_create_callback(); } phase_ = Phase::Ready; @@ -641,6 +644,13 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( return service_isolate->isolate(); } +DartIsolateGroupData& DartIsolate::GetIsolateGroupData() { + std::shared_ptr* isolate_group_data = + static_cast*>( + Dart_IsolateGroupData(isolate())); + return **isolate_group_data; +} + // |Dart_IsolateGroupCreateCallback| Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback( const char* advisory_script_uri, @@ -648,10 +658,10 @@ Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback( const char* package_root, const char* package_config, Dart_IsolateFlags* flags, - std::shared_ptr* parent_embedder_isolate, + std::shared_ptr* parent_isolate_data, char** error) { TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCreateCallback"); - if (parent_embedder_isolate == nullptr && + if (parent_isolate_data == nullptr && strcmp(advisory_script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) { // The VM attempts to start the VM service for us on |Dart_Initialize|. In // such a case, the callback data will be null and the script URI will be @@ -665,17 +675,44 @@ Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback( ); } - return CreateDartVMAndEmbedderObjectPair( - advisory_script_uri, // URI - advisory_script_entrypoint, // entrypoint - package_root, // package root - package_config, // package config - flags, // isolate flags - parent_embedder_isolate, // embedder data - false, // is root isolate - error // error - ) - .first; + DartIsolateGroupData& parent_group_data = + (*parent_isolate_data)->GetIsolateGroupData(); + + auto isolate_group_data = + std::make_unique>( + std::shared_ptr(new DartIsolateGroupData( + parent_group_data.GetSettings(), + parent_group_data.GetIsolateSnapshot(), advisory_script_uri, + advisory_script_entrypoint, + parent_group_data.GetChildIsolatePreparer(), + parent_group_data.GetIsolateCreateCallback(), + parent_group_data.GetIsolateShutdownCallback()))); + + TaskRunners null_task_runners(advisory_script_uri, + /* platform= */ nullptr, /* gpu= */ nullptr, + /* ui= */ nullptr, + /* io= */ nullptr); + + auto isolate_data = std::make_unique>( + std::shared_ptr(new DartIsolate( + (*isolate_group_data)->GetSettings(), // settings + null_task_runners, // task_runners + fml::WeakPtr{}, // snapshot_delegate + fml::WeakPtr{}, // io_manager + fml::RefPtr{}, // unref_queue + fml::WeakPtr{}, // image_decoder + advisory_script_uri, // advisory_script_uri + advisory_script_entrypoint, // advisory_script_entrypoint + false))); // is_root_isolate + + Dart_Isolate vm_isolate = CreateDartIsolateGroup( + std::move(isolate_group_data), std::move(isolate_data), flags, error); + + if (*error) { + FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << error; + } + + return vm_isolate; } // |Dart_IsolateInitializeCallback| @@ -689,36 +726,29 @@ bool DartIsolate::DartIsolateInitializeCallback(void** child_callback_data, return false; } - auto* root_embedder_isolate = static_cast*>( - Dart_CurrentIsolateGroupData()); + auto* isolate_group_data = + static_cast*>( + Dart_CurrentIsolateGroupData()); - TaskRunners null_task_runners( - (*root_embedder_isolate)->GetAdvisoryScriptURI(), - /* platform= */ nullptr, /* gpu= */ nullptr, - /* ui= */ nullptr, - /* io= */ nullptr); + TaskRunners null_task_runners((*isolate_group_data)->GetAdvisoryScriptURI(), + /* platform= */ nullptr, /* gpu= */ nullptr, + /* ui= */ nullptr, + /* io= */ nullptr); auto embedder_isolate = std::make_unique>( std::shared_ptr(new DartIsolate( - (*root_embedder_isolate)->GetSettings(), // settings - (*root_embedder_isolate)->GetIsolateSnapshot(), // isolate_snapshot - null_task_runners, // task_runners - fml::WeakPtr{}, // snapshot_delegate - fml::WeakPtr{}, // io_manager - fml::RefPtr{}, // unref_queue - fml::WeakPtr{}, // image_decoder - (*root_embedder_isolate) - ->GetAdvisoryScriptURI(), // advisory_script_uri - (*root_embedder_isolate) + (*isolate_group_data)->GetSettings(), // settings + null_task_runners, // task_runners + fml::WeakPtr{}, // snapshot_delegate + fml::WeakPtr{}, // io_manager + fml::RefPtr{}, // unref_queue + fml::WeakPtr{}, // image_decoder + (*isolate_group_data)->GetAdvisoryScriptURI(), // advisory_script_uri + (*isolate_group_data) ->GetAdvisoryScriptEntrypoint(), // advisory_script_entrypoint - (*root_embedder_isolate)->child_isolate_preparer_, // preparer - (*root_embedder_isolate)->isolate_create_callback_, // on create - (*root_embedder_isolate)->isolate_shutdown_callback_, // on shutdown - false, // is_root_isolate - false))); // is_group_root_isolate - - // root isolate should have been created via CreateRootIsolate and - // CreateDartVMAndEmbedderObjectPair + false))); // is_root_isolate + + // root isolate should have been created via CreateRootIsolate if (!InitializeIsolate(*embedder_isolate, isolate, error)) { return false; } @@ -731,84 +761,35 @@ bool DartIsolate::DartIsolateInitializeCallback(void** child_callback_data, return true; } -std::pair> -DartIsolate::CreateDartVMAndEmbedderObjectPair( - const char* advisory_script_uri, - const char* advisory_script_entrypoint, - const char* package_root, - const char* package_config, +Dart_Isolate DartIsolate::CreateDartIsolateGroup( + std::unique_ptr> isolate_group_data, + std::unique_ptr> isolate_data, Dart_IsolateFlags* flags, - std::shared_ptr* p_parent_embedder_isolate, - bool is_root_isolate, char** error) { - TRACE_EVENT0("flutter", "DartIsolate::CreateDartVMAndEmbedderObjectPair"); - - std::unique_ptr> embedder_isolate( - p_parent_embedder_isolate); - - if (embedder_isolate == nullptr) { - *error = - strdup("Parent isolate did not have embedder specific callback data."); - FML_DLOG(ERROR) << *error; - return {nullptr, {}}; - } - - if (!is_root_isolate) { - auto* raw_embedder_isolate = embedder_isolate.release(); - - TaskRunners null_task_runners(advisory_script_uri, nullptr, nullptr, - nullptr, nullptr); - - // Copy most fields from the parent to the child. - embedder_isolate = std::make_unique>( - std::shared_ptr(new DartIsolate( - (*raw_embedder_isolate)->GetSettings(), // settings - (*raw_embedder_isolate)->GetIsolateSnapshot(), // isolate_snapshot - null_task_runners, // task_runners - fml::WeakPtr{}, // snapshot_delegate - fml::WeakPtr{}, // io_manager - fml::RefPtr{}, // unref_queue - fml::WeakPtr{}, // image_decoder - advisory_script_uri, // advisory_script_uri - advisory_script_entrypoint, // advisory_script_entrypoint - (*raw_embedder_isolate)->child_isolate_preparer_, // preparer - (*raw_embedder_isolate)->isolate_create_callback_, // on create - (*raw_embedder_isolate)->isolate_shutdown_callback_, // on shutdown - is_root_isolate, - true)) // is_root_group_isolate - ); - } + TRACE_EVENT0("flutter", "DartIsolate::CreateDartIsolateGroup"); // Create the Dart VM isolate and give it the embedder object as the baton. Dart_Isolate isolate = Dart_CreateIsolateGroup( - advisory_script_uri, // - advisory_script_entrypoint, // - (*embedder_isolate)->GetIsolateSnapshot()->GetDataMapping(), - (*embedder_isolate)->GetIsolateSnapshot()->GetInstructionsMapping(), - flags, - embedder_isolate.get(), // isolate_group_data - embedder_isolate.get(), // isolate_group - error); + (*isolate_group_data)->GetAdvisoryScriptURI().c_str(), + (*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(), + (*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(), + (*isolate_group_data)->GetIsolateSnapshot()->GetInstructionsMapping(), + flags, isolate_group_data.get(), isolate_data.get(), error); if (isolate == nullptr) { - FML_DLOG(ERROR) << *error; - return {nullptr, {}}; - } - - if (!InitializeIsolate(*embedder_isolate, isolate, error)) { - return {nullptr, {}}; + return nullptr; } - auto* isolate_data = static_cast*>( - Dart_IsolateGroupData(isolate)); - FML_DCHECK(isolate_data->get() == embedder_isolate->get()); + // Ownership of the isolate data objects has been transferred to the Dart VM. + std::shared_ptr embedder_isolate(*isolate_data); + isolate_group_data.release(); + isolate_data.release(); - auto weak_embedder_isolate = (*embedder_isolate)->GetWeakIsolatePtr(); + if (!InitializeIsolate(std::move(embedder_isolate), isolate, error)) { + return nullptr; + } - // The ownership of the embedder object is controlled by the Dart VM. So the - // only reference returned to the caller is weak. - embedder_isolate.release(); - return {isolate, weak_embedder_isolate}; + return isolate; } bool DartIsolate::InitializeIsolate( @@ -833,8 +814,10 @@ bool DartIsolate::InitializeIsolate( // also a root isolate) by the utility routines in the VM. However, secondary // isolates will be run by the VM if they are marked as runnable. if (!embedder_isolate->IsRootIsolate()) { - FML_DCHECK(embedder_isolate->child_isolate_preparer_); - if (!embedder_isolate->child_isolate_preparer_(embedder_isolate.get())) { + const ChildIsolatePreparer& child_isolate_preparer = + embedder_isolate->GetIsolateGroupData().GetChildIsolatePreparer(); + FML_DCHECK(child_isolate_preparer); + if (!child_isolate_preparer(embedder_isolate.get())) { *error = strdup("Could not prepare the child isolate to run."); FML_DLOG(ERROR) << *error; return false; @@ -846,7 +829,7 @@ bool DartIsolate::InitializeIsolate( // |Dart_IsolateShutdownCallback| void DartIsolate::DartIsolateShutdownCallback( - std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_group_data, std::shared_ptr* isolate_data) { TRACE_EVENT0("flutter", "DartIsolate::DartIsolateShutdownCallback"); FML_DLOG(INFO) << "DartIsolateShutdownCallback" @@ -857,7 +840,7 @@ void DartIsolate::DartIsolateShutdownCallback( // |Dart_IsolateGroupCleanupCallback| void DartIsolate::DartIsolateGroupCleanupCallback( - std::shared_ptr* isolate_data) { + std::shared_ptr* isolate_data) { TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCleanupCallback"); FML_DLOG(INFO) << "DartIsolateGroupCleanupCallback isolate_data " << isolate_data; @@ -867,38 +850,15 @@ void DartIsolate::DartIsolateGroupCleanupCallback( // |Dart_IsolateCleanupCallback| void DartIsolate::DartIsolateCleanupCallback( - std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_group_data, std::shared_ptr* isolate_data) { TRACE_EVENT0("flutter", "DartIsolate::DartIsolateCleanupCallback"); - if ((*isolate_data)->IsRootIsolate()) { - // isolate_data will be cleaned up as part of IsolateGroup cleanup - FML_DLOG(INFO) - << "DartIsolateCleanupCallback no-op for root isolate isolate_data " - << isolate_data; - return; - } - if ((*isolate_data)->IsGroupRootIsolate()) { - // Even if isolate was not a root isolate(i.e. was spawned), - // it might have IsolateGroup created for it (when - // --no-enable-isolate-groups dart vm flag is used). - // Then its isolate_data will be cleaned up as part of IsolateGroup - // cleanup as well. - FML_DLOG(INFO) << "DartIsolateCleanupCallback no-op for group root isolate " - "isolate_data " - << isolate_data; - return; - } - FML_DLOG(INFO) << "DartIsolateCleanupCallback cleaned up isolate_data " << isolate_data; delete isolate_data; } -fml::RefPtr DartIsolate::GetIsolateSnapshot() const { - return isolate_snapshot_; -} - std::weak_ptr DartIsolate::GetWeakIsolatePtr() { return std::static_pointer_cast(shared_from_this()); } @@ -917,8 +877,11 @@ void DartIsolate::OnShutdownCallback() { } shutdown_callbacks_.clear(); - if (isolate_shutdown_callback_) { - isolate_shutdown_callback_(); + + const fml::closure& isolate_shutdown_callback = + GetIsolateGroupData().GetIsolateShutdownCallback(); + if (isolate_shutdown_callback) { + isolate_shutdown_callback(); } } diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index 100a16fea9f6a..efbc6bde21755 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -24,6 +24,7 @@ namespace flutter { class DartVM; +class DartIsolateGroupData; //------------------------------------------------------------------------------ /// @brief Represents an instance of a live isolate. An isolate is a @@ -205,13 +206,6 @@ class DartIsolate : public UIDartState { // |UIDartState| ~DartIsolate() override; - //---------------------------------------------------------------------------- - /// @brief Get the settings used to create this isolate instance. - /// - /// @return The settings used in the `CreateRootIsolate` call. - /// - const Settings& GetSettings() const; - //---------------------------------------------------------------------------- /// @brief The current phase of the isolate. The engine represents all /// dart isolates as being in one of the known phases. By invoking @@ -376,14 +370,6 @@ class DartIsolate : public UIDartState { /// void AddIsolateShutdownCallback(const fml::closure& closure); - //---------------------------------------------------------------------------- - /// @brief The snapshot used to launch this isolate. This is referenced - /// by any child isolates launched by the root isolate. - /// - /// @return The isolate snapshot. - /// - fml::RefPtr GetIsolateSnapshot() const; - //---------------------------------------------------------------------------- /// @brief A weak pointer to the Dart isolate instance. This instance may /// only be used on the task runner that created the root isolate. @@ -403,14 +389,8 @@ class DartIsolate : public UIDartState { // Root isolate of the VM application bool IsRootIsolate() const { return is_root_isolate_; } - // Isolate that owns IsolateGroup it lives in. - // When --no-enable-isolate-groups dart vm flag is set, - // all child isolates will have their own IsolateGroups. - bool IsGroupRootIsolate() const { return is_group_root_isolate_; } private: - using ChildIsolatePreparer = std::function; - class AutoFireClosure { public: AutoFireClosure(const fml::closure& closure); @@ -424,19 +404,12 @@ class DartIsolate : public UIDartState { friend class DartVM; Phase phase_ = Phase::Unknown; - const Settings settings_; - const fml::RefPtr isolate_snapshot_; std::vector> kernel_buffers_; std::vector> shutdown_callbacks_; - ChildIsolatePreparer child_isolate_preparer_ = nullptr; fml::RefPtr message_handling_task_runner_; - const fml::closure isolate_create_callback_; - const fml::closure isolate_shutdown_callback_; const bool is_root_isolate_; - const bool is_group_root_isolate_; DartIsolate(const Settings& settings, - fml::RefPtr isolate_snapshot, TaskRunners task_runners, fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, @@ -444,11 +417,7 @@ class DartIsolate : public UIDartState { fml::WeakPtr image_decoder, std::string advisory_script_uri, std::string advisory_script_entrypoint, - const ChildIsolatePreparer& child_isolate_preparer, - const fml::closure& isolate_create_callback, - const fml::closure& isolate_shutdown_callback, - bool is_root_isolate, - bool is_group_root_isolate); + bool is_root_isolate); FML_WARN_UNUSED_RESULT bool Initialize(Dart_Isolate isolate); void SetMessageHandlingTaskRunner(fml::RefPtr runner); @@ -465,6 +434,8 @@ class DartIsolate : public UIDartState { void OnShutdownCallback(); + DartIsolateGroupData& GetIsolateGroupData(); + // |Dart_IsolateGroupCreateCallback| static Dart_Isolate DartIsolateGroupCreateCallback( const char* advisory_script_uri, @@ -472,7 +443,7 @@ class DartIsolate : public UIDartState { const char* package_root, const char* package_config, Dart_IsolateFlags* flags, - std::shared_ptr* embedder_isolate, + std::shared_ptr* parent_isolate_group, char** error); // |Dart_IsolateInitializeCallback| @@ -485,16 +456,10 @@ class DartIsolate : public UIDartState { Dart_IsolateFlags* flags, char** error); - static std::pair /* embedder */> - CreateDartVMAndEmbedderObjectPair( - const char* advisory_script_uri, - const char* advisory_script_entrypoint, - const char* package_root, - const char* package_config, + static Dart_Isolate CreateDartIsolateGroup( + std::unique_ptr> isolate_group_data, + std::unique_ptr> isolate_data, Dart_IsolateFlags* flags, - std::shared_ptr* parent_embedder_isolate, - bool is_root_isolate, char** error); static bool InitializeIsolate(std::shared_ptr embedder_isolate, @@ -503,17 +468,17 @@ class DartIsolate : public UIDartState { // |Dart_IsolateShutdownCallback| static void DartIsolateShutdownCallback( - std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_group_data, std::shared_ptr* isolate_data); // |Dart_IsolateCleanupCallback| static void DartIsolateCleanupCallback( - std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_group_data, std::shared_ptr* isolate_data); // |Dart_IsolateGroupCleanupCallback| static void DartIsolateGroupCleanupCallback( - std::shared_ptr* isolate_group_data); + std::shared_ptr* isolate_group_data); FML_DISALLOW_COPY_AND_ASSIGN(DartIsolate); }; diff --git a/runtime/dart_isolate_group_data.cc b/runtime/dart_isolate_group_data.cc new file mode 100644 index 0000000000000..20a61894ff680 --- /dev/null +++ b/runtime/dart_isolate_group_data.cc @@ -0,0 +1,65 @@ +// 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_isolate_group_data.h" +#include "flutter/runtime/dart_snapshot.h" + +namespace flutter { + +DartIsolateGroupData::DartIsolateGroupData( + const Settings& settings, + fml::RefPtr isolate_snapshot, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + const ChildIsolatePreparer& child_isolate_preparer, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback) + : settings_(settings), + isolate_snapshot_(isolate_snapshot), + advisory_script_uri_(advisory_script_uri), + advisory_script_entrypoint_(advisory_script_entrypoint), + child_isolate_preparer_(child_isolate_preparer), + isolate_create_callback_(isolate_create_callback), + isolate_shutdown_callback_(isolate_shutdown_callback) { + FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot."; +} + +DartIsolateGroupData::~DartIsolateGroupData() = default; + +const Settings& DartIsolateGroupData::GetSettings() const { + return settings_; +} + +fml::RefPtr DartIsolateGroupData::GetIsolateSnapshot() + const { + return isolate_snapshot_; +} + +const std::string& DartIsolateGroupData::GetAdvisoryScriptURI() const { + return advisory_script_uri_; +} + +const std::string& DartIsolateGroupData::GetAdvisoryScriptEntrypoint() const { + return advisory_script_entrypoint_; +} + +const ChildIsolatePreparer& DartIsolateGroupData::GetChildIsolatePreparer() + const { + return child_isolate_preparer_; +} + +const fml::closure& DartIsolateGroupData::GetIsolateCreateCallback() const { + return isolate_create_callback_; +} + +const fml::closure& DartIsolateGroupData::GetIsolateShutdownCallback() const { + return isolate_shutdown_callback_; +} + +void DartIsolateGroupData::SetChildIsolatePreparer( + const ChildIsolatePreparer& value) { + child_isolate_preparer_ = value; +} + +} // namespace flutter diff --git a/runtime/dart_isolate_group_data.h b/runtime/dart_isolate_group_data.h new file mode 100644 index 0000000000000..400831aee5ec8 --- /dev/null +++ b/runtime/dart_isolate_group_data.h @@ -0,0 +1,63 @@ +// 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_ISOLATE_GROUP_DATA_H_ +#define FLUTTER_RUNTIME_DART_ISOLATE_GROUP_DATA_H_ + +#include + +#include "flutter/common/settings.h" +#include "flutter/fml/closure.h" +#include "flutter/fml/memory/ref_ptr.h" + +namespace flutter { + +class DartIsolate; +class DartSnapshot; + +using ChildIsolatePreparer = std::function; + +// Object holding state associated with a Dart isolate group. An instance of +// this class will be provided to Dart_CreateIsolateGroup as the +// isolate_group_data. +// +// This object must be thread safe because the Dart VM can invoke the isolate +// group cleanup callback on any thread. +class DartIsolateGroupData { + public: + DartIsolateGroupData(const Settings& settings, + fml::RefPtr isolate_snapshot, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + const ChildIsolatePreparer& child_isolate_preparer, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback); + + ~DartIsolateGroupData(); + + const Settings& GetSettings() const; + fml::RefPtr GetIsolateSnapshot() const; + const std::string& GetAdvisoryScriptURI() const; + const std::string& GetAdvisoryScriptEntrypoint() const; + const ChildIsolatePreparer& GetChildIsolatePreparer() const; + const fml::closure& GetIsolateCreateCallback() const; + const fml::closure& GetIsolateShutdownCallback() const; + + void SetChildIsolatePreparer(const ChildIsolatePreparer& value); + + private: + FML_DISALLOW_COPY_AND_ASSIGN(DartIsolateGroupData); + + const Settings settings_; + const fml::RefPtr isolate_snapshot_; + const std::string advisory_script_uri_; + const std::string advisory_script_entrypoint_; + ChildIsolatePreparer child_isolate_preparer_; + const fml::closure isolate_create_callback_; + const fml::closure isolate_shutdown_callback_; +}; + +} // namespace flutter + +#endif // FLUTTER_RUNTIME_DART_ISOLATE_GROUP_DATA_H_ diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index 33b60ae26eefc..79ea7db2aded1 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -109,14 +109,15 @@ class AutoIsolateShutdown { return; } fml::AutoResetWaitableEvent latch; - fml::TaskRunner::RunNowOrPostTask(runner_, [isolate = isolate_, &latch]() { - FML_LOG(INFO) << "Shutting down isolate."; - if (!isolate->Shutdown()) { - FML_LOG(ERROR) << "Could not shutdown isolate."; - FML_CHECK(false); - } - latch.Signal(); - }); + fml::TaskRunner::RunNowOrPostTask( + runner_, [isolate = std::move(isolate_), &latch]() { + FML_LOG(INFO) << "Shutting down isolate."; + if (!isolate->Shutdown()) { + FML_LOG(ERROR) << "Could not shutdown isolate."; + FML_CHECK(false); + } + latch.Signal(); + }); latch.Wait(); }