diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index f82e0d4eccdc4..9cb2fce5e91a6 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -73,6 +73,29 @@ Dart_IsolateFlags DartIsolate::Flags::Get() const { return flags_; } +std::weak_ptr DartIsolate::SpawnIsolate( + const Settings& settings, + std::unique_ptr platform_configuration, + fml::WeakPtr snapshot_delegate, + fml::WeakPtr hint_freed_delegate, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + Flags flags, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback, + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configration) const { + return CreateRunningRootIsolate( + settings, GetIsolateGroupData().GetIsolateSnapshot(), GetTaskRunners(), + std::move(platform_configuration), snapshot_delegate, hint_freed_delegate, + GetIOManager(), GetSkiaUnrefQueue(), GetImageDecoder(), + advisory_script_uri, advisory_script_entrypoint, flags, + isolate_create_callback, isolate_shutdown_callback, dart_entrypoint, + dart_entrypoint_library, std::move(isolate_configration), + GetVolatilePathTracker(), this); +} + std::weak_ptr DartIsolate::CreateRunningRootIsolate( const Settings& settings, fml::RefPtr isolate_snapshot, @@ -91,7 +114,8 @@ std::weak_ptr DartIsolate::CreateRunningRootIsolate( std::optional dart_entrypoint, std::optional dart_entrypoint_library, std::unique_ptr isolate_configration, - std::shared_ptr volatile_path_tracker) { + std::shared_ptr volatile_path_tracker, + const DartIsolate* spawning_isolate) { if (!isolate_snapshot) { FML_LOG(ERROR) << "Invalid isolate snapshot."; return {}; @@ -135,7 +159,8 @@ std::weak_ptr DartIsolate::CreateRunningRootIsolate( }); if (isolate->GetPhase() != DartIsolate::Phase::LibrariesSetup) { - FML_LOG(ERROR) << "Root isolate was created in an incorrect phase."; + FML_LOG(ERROR) << "Root isolate was created in an incorrect phase: " + << static_cast(isolate->GetPhase()); return {}; } @@ -190,7 +215,8 @@ std::weak_ptr DartIsolate::CreateRootIsolate( Flags flags, const fml::closure& isolate_create_callback, const fml::closure& isolate_shutdown_callback, - std::shared_ptr volatile_path_tracker) { + std::shared_ptr volatile_path_tracker, + const DartIsolate* spawning_isolate) { TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate"); // The child isolate preparer is null but will be set when the isolate is @@ -223,13 +249,28 @@ std::weak_ptr DartIsolate::CreateRootIsolate( ))); DartErrorString error; + Dart_Isolate vm_isolate = nullptr; auto isolate_flags = flags.Get(); - Dart_Isolate vm_isolate = CreateDartIsolateGroup( + /// TODO(b/72025) This will be where we call Dart_CreateIsolateInGroup if + /// spawning_isolate != nullptr. + vm_isolate = CreateDartIsolateGroup( std::move(isolate_group_data), std::move(isolate_data), &isolate_flags, - error.error()); + error.error(), + [](std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_data, Dart_IsolateFlags* flags, + char** error) { + return Dart_CreateIsolateGroup( + (*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, isolate_data, error); + }); if (error) { - FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << error.str(); + FML_LOG(ERROR) << "CreateRootIsolate failed: " << error.str(); } if (vm_isolate == nullptr) { @@ -809,6 +850,11 @@ DartIsolateGroupData& DartIsolate::GetIsolateGroupData() { return **isolate_group_data; } +const DartIsolateGroupData& DartIsolate::GetIsolateGroupData() const { + DartIsolate* non_const_this = const_cast(this); + return non_const_this->GetIsolateGroupData(); +} + // |Dart_IsolateGroupCreateCallback| Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback( const char* advisory_script_uri, @@ -871,7 +917,19 @@ Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback( nullptr))); // volatile path tracker Dart_Isolate vm_isolate = CreateDartIsolateGroup( - std::move(isolate_group_data), std::move(isolate_data), flags, error); + std::move(isolate_group_data), std::move(isolate_data), flags, error, + [](std::shared_ptr* isolate_group_data, + std::shared_ptr* isolate_data, Dart_IsolateFlags* flags, + char** error) { + return Dart_CreateIsolateGroup( + (*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, isolate_data, error); + }); if (*error) { FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << error; @@ -933,16 +991,16 @@ Dart_Isolate DartIsolate::CreateDartIsolateGroup( std::unique_ptr> isolate_group_data, std::unique_ptr> isolate_data, Dart_IsolateFlags* flags, - char** error) { + char** error, + std::function*, + std::shared_ptr*, + Dart_IsolateFlags*, + char**)> make_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( - (*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); + Dart_Isolate isolate = + make_isolate(isolate_group_data.get(), isolate_data.get(), flags, error); if (isolate == nullptr) { return nullptr; diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index 81a4c8b1ee6a6..b4705ad9c7b76 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -19,7 +19,6 @@ #include "flutter/lib/ui/io_manager.h" #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/lib/ui/ui_dart_state.h" -#include "flutter/lib/ui/volatile_path_tracker.h" #include "flutter/lib/ui/window/platform_configuration.h" #include "flutter/runtime/dart_snapshot.h" #include "third_party/dart/runtime/include/dart_api.h" @@ -207,7 +206,9 @@ class DartIsolate : public UIDartState { /// for all isolate shutdowns /// (including the children of the /// root isolate). - /// + /// @param[in] spawning_isolate The isolate that is spawning the + /// new isolate. See also + /// DartIsolate::SpawnIsolate. /// @return A weak pointer to the root Dart isolate. The caller must /// ensure that the isolate is not referenced for long periods of /// time as it prevents isolate collection when the isolate @@ -232,7 +233,37 @@ class DartIsolate : public UIDartState { std::optional dart_entrypoint, std::optional dart_entrypoint_library, std::unique_ptr isolate_configration, - std::shared_ptr volatile_path_tracker); + std::shared_ptr volatile_path_tracker, + const DartIsolate* spawning_isolate = nullptr); + + //---------------------------------------------------------------------------- + /// @brief Creates a running DartIsolate who shares as many resources as + /// possible with the caller DartIsolate. This allows them to + /// occupy less memory together and to be created faster. + /// @details Shared components will be destroyed when the last live + /// DartIsolate is destroyed. SpawnIsolate can only be used to + /// create DartIsolates whose executable code is shared with the + /// calling DartIsolate. + /// @attention Only certain setups can take advantage of the most savings + /// currently, AOT specifically. + /// @return A weak pointer to a new running DartIsolate. The caller must + /// ensure that the isolate is not referenced for long periods of + /// time as it prevents isolate collection when the isolate + /// terminates itself. The caller may also only use the isolate on + /// the thread on which the isolate was created. + std::weak_ptr SpawnIsolate( + const Settings& settings, + std::unique_ptr platform_configuration, + fml::WeakPtr snapshot_delegate, + fml::WeakPtr hint_freed_delegate, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + Flags flags, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback, + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configration) const; // |UIDartState| ~DartIsolate() override; @@ -433,7 +464,8 @@ class DartIsolate : public UIDartState { Flags flags, const fml::closure& isolate_create_callback, const fml::closure& isolate_shutdown_callback, - std::shared_ptr volatile_path_tracker); + std::shared_ptr volatile_path_tracker, + const DartIsolate* spawning_isolate = nullptr); DartIsolate(const Settings& settings, TaskRunners task_runners, @@ -463,6 +495,8 @@ class DartIsolate : public UIDartState { DartIsolateGroupData& GetIsolateGroupData(); + const DartIsolateGroupData& GetIsolateGroupData() const; + // |Dart_IsolateGroupCreateCallback| static Dart_Isolate DartIsolateGroupCreateCallback( const char* advisory_script_uri, @@ -487,7 +521,11 @@ class DartIsolate : public UIDartState { std::unique_ptr> isolate_group_data, std::unique_ptr> isolate_data, Dart_IsolateFlags* flags, - char** error); + char** error, + std::function*, + std::shared_ptr*, + Dart_IsolateFlags*, + char**)> make_isolate); static bool InitializeIsolate(std::shared_ptr embedder_isolate, Dart_Isolate isolate, diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index 1b59e70c81621..3b25c02dec0ae 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -77,6 +77,69 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) { ASSERT_TRUE(root_isolate->Shutdown()); } +TEST_F(DartIsolateTest, SpawnIsolate) { + ASSERT_FALSE(DartVMRef::IsInstanceRunning()); + auto settings = CreateSettingsForFixture(); + auto vm_ref = DartVMRef::Create(settings); + ASSERT_TRUE(vm_ref); + auto vm_data = vm_ref.GetVMData(); + ASSERT_TRUE(vm_data); + TaskRunners task_runners(GetCurrentTestName(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner() // + ); + + auto isolate_configuration = + IsolateConfiguration::InferFromSettings(settings); + + auto weak_isolate = DartIsolate::CreateRunningRootIsolate( + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // hint freed delegate + {}, // io manager + {}, // unref queue + {}, // image decoder + "main.dart", // advisory uri + "main", // advisory entrypoint, + DartIsolate::Flags{}, // flags + settings.isolate_create_callback, // isolate create callback + settings.isolate_shutdown_callback, // isolate shutdown callback + "main", // dart entrypoint + std::nullopt, // dart entrypoint library + std::move(isolate_configuration), // isolate configuration + nullptr // Volatile path tracker + ); + auto root_isolate = weak_isolate.lock(); + ASSERT_TRUE(root_isolate); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running); + + auto spawn_configuration = IsolateConfiguration::InferFromSettings(settings); + + auto weak_spawn = root_isolate->SpawnIsolate( + /*settings=*/vm_data->GetSettings(), + /*platform_configuration=*/nullptr, + /*snapshot_delegate=*/{}, + /*hint_freed_delegate=*/{}, + /*advisory_script_uri=*/"main.dart", + /*advisory_script_entrypoint=*/"main", + /*flags=*/DartIsolate::Flags{}, + /*isolate_create_callback=*/settings.isolate_create_callback, + /*isolate_shutdown_callback=*/settings.isolate_shutdown_callback, + /*dart_entrypoint=*/"main", + /*dart_entrypoint_library=*/std::nullopt, + /*isolate_configration=*/std::move(spawn_configuration)); + auto spawn = weak_spawn.lock(); + ASSERT_TRUE(spawn); + ASSERT_EQ(spawn->GetPhase(), DartIsolate::Phase::Running); + ASSERT_TRUE(spawn->Shutdown()); + ASSERT_TRUE(root_isolate->Shutdown()); +} + TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); auto settings = CreateSettingsForFixture(); diff --git a/runtime/dart_vm_lifecycle.h b/runtime/dart_vm_lifecycle.h index 5c355abe9bbc6..87ad135e0a028 100644 --- a/runtime/dart_vm_lifecycle.h +++ b/runtime/dart_vm_lifecycle.h @@ -31,6 +31,8 @@ class DartVMRef { fml::RefPtr vm_snapshot = nullptr, fml::RefPtr isolate_snapshot = nullptr); + DartVMRef(const DartVMRef&) = default; + DartVMRef(DartVMRef&&); ~DartVMRef(); @@ -53,11 +55,21 @@ class DartVMRef { return vm_.get(); } + const DartVM* get() const { + FML_DCHECK(vm_); + return vm_.get(); + } + DartVM* operator->() { FML_DCHECK(vm_); return vm_.get(); } + const DartVM* operator->() const { + FML_DCHECK(vm_); + return vm_.get(); + } + DartVM* operator&() { FML_DCHECK(vm_); return vm_.get(); @@ -72,8 +84,6 @@ class DartVMRef { // Only used by Dart Isolate to register itself with the VM. static DartVM* GetRunningVM(); - - FML_DISALLOW_COPY_AND_ASSIGN(DartVMRef); }; } // namespace flutter diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 4998a9aeb3f50..42a6ea6bc9d67 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -57,6 +57,25 @@ RuntimeController::RuntimeController( persistent_isolate_data_(std::move(p_persistent_isolate_data)), volatile_path_tracker_(std::move(p_volatile_path_tracker)) {} +std::unique_ptr RuntimeController::Spawn( + RuntimeDelegate& client, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + const std::function& idle_notification_callback, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback, + std::shared_ptr persistent_isolate_data) const { + auto result = std::make_unique( + client, vm_, isolate_snapshot_, task_runners_, snapshot_delegate_, + hint_freed_delegate_, io_manager_, unref_queue_, image_decoder_, + advisory_script_uri, advisory_script_entrypoint, + idle_notification_callback, platform_data_, isolate_create_callback, + isolate_shutdown_callback, persistent_isolate_data, + volatile_path_tracker_); + result->spawning_isolate_ = root_isolate_; + return result; +} + RuntimeController::~RuntimeController() { FML_DCHECK(Dart_CurrentIsolate() == nullptr); std::shared_ptr root_isolate = root_isolate_.lock(); diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index 5e2c26da52726..ba95ca2cae830 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -133,6 +133,22 @@ class RuntimeController : public PlatformConfigurationClient { std::shared_ptr persistent_isolate_data, std::shared_ptr volatile_path_tracker); + //---------------------------------------------------------------------------- + /// @brief Create a RuntimeController that shares as many resources as + /// possible with the calling RuntimeController such that together + /// they occupy less memory. + /// @return A RuntimeController with a running isolate. + /// @see RuntimeController::RuntimeController + /// + std::unique_ptr Spawn( + RuntimeDelegate& client, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + const std::function& idle_notification_callback, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback, + std::shared_ptr persistent_isolate_data) const; + // |PlatformConfigurationClient| ~RuntimeController() override; @@ -542,6 +558,23 @@ class RuntimeController : public PlatformConfigurationClient { // |PlatformConfigurationClient| void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; + const fml::WeakPtr& GetIOManager() const { return io_manager_; } + + DartVM* GetDartVM() const { return vm_; } + + const fml::RefPtr& GetIsolateSnapshot() const { + return isolate_snapshot_; + } + + const PlatformData& GetPlatformData() const { return platform_data_; } + + const fml::RefPtr& GetSkiaUnrefQueue() const { + return unref_queue_; + } + + const fml::WeakPtr& GetSnapshotDelegate() const { + return snapshot_delegate_; + } protected: /// Constructor for Mocks. @@ -576,6 +609,7 @@ class RuntimeController : public PlatformConfigurationClient { std::function idle_notification_callback_; PlatformData platform_data_; std::weak_ptr root_isolate_; + std::weak_ptr spawning_isolate_; std::optional root_isolate_return_code_; const fml::closure isolate_create_callback_; const fml::closure isolate_shutdown_callback_; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 84de3e25bf92c..1d194e4fc7341 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -97,6 +97,33 @@ Engine::Engine(Delegate& delegate, ); } +std::unique_ptr Engine::Spawn( + Delegate& delegate, + const PointerDataDispatcherMaker& dispatcher_maker, + Settings settings, + std::unique_ptr animator) const { + auto result = std::make_unique( + /*delegate=*/delegate, + /*dispatcher_maker=*/dispatcher_maker, + /*image_decoder_task_runner=*/ + runtime_controller_->GetDartVM()->GetConcurrentWorkerTaskRunner(), + /*task_runners=*/task_runners_, + /*settings=*/settings, + /*animator=*/std::move(animator), + /*io_manager=*/runtime_controller_->GetIOManager(), + /*runtime_controller=*/nullptr); + result->runtime_controller_ = runtime_controller_->Spawn( + *result, // runtime delegate + settings_.advisory_script_uri, // advisory script uri + settings_.advisory_script_entrypoint, // advisory script entrypoint + settings_.idle_notification_callback, // idle notification callback + settings_.isolate_create_callback, // isolate create callback + settings_.isolate_shutdown_callback, // isolate shutdown callback + settings_.persistent_isolate_data // persistent isolate data + ); + return result; +} + Engine::~Engine() = default; fml::WeakPtr Engine::GetWeakPtr() const { diff --git a/shell/common/engine.h b/shell/common/engine.h index 8041e14199add..cfcab91e302c7 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -354,6 +354,23 @@ class Engine final : public RuntimeDelegate, fml::WeakPtr snapshot_delegate, std::shared_ptr volatile_path_tracker); + //---------------------------------------------------------------------------- + /// @brief Create a Engine that shares as many resources as + /// possible with the calling Engine such that together + /// they occupy less memory and be created faster. + /// @details This method ultimately calls DartIsolate::SpawnIsolate to make + /// sure resources are shared. This should only be called on + /// running Engines. + /// @return A new Engine with a running isolate. + /// @see Engine::Engine + /// @see DartIsolate::SpawnIsolate + /// + std::unique_ptr Spawn( + Delegate& delegate, + const PointerDataDispatcherMaker& dispatcher_maker, + Settings settings, + std::unique_ptr animator) const; + //---------------------------------------------------------------------------- /// @brief Destroys the engine engine. Called by the shell on the UI task /// runner. The running root isolate is terminated and will no diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 98d8f43f2813c..4e4fe568c0769 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -20,7 +20,6 @@ #include "flutter/fml/paths.h" #include "flutter/fml/trace_event.h" #include "flutter/fml/unique_fd.h" -#include "flutter/lib/ui/painting/path.h" #include "flutter/runtime/dart_vm.h" #include "flutter/shell/common/engine.h" #include "flutter/shell/common/skia_event_tracer_impl.h" @@ -40,6 +39,35 @@ constexpr char kSystemChannel[] = "flutter/system"; constexpr char kTypeKey[] = "type"; constexpr char kFontChange[] = "fontsChange"; +namespace { +std::unique_ptr CreateEngine( + Engine::Delegate& delegate, + const PointerDataDispatcherMaker& dispatcher_maker, + DartVM& vm, + fml::RefPtr isolate_snapshot, + TaskRunners task_runners, + const PlatformData platform_data, + Settings settings, + std::unique_ptr animator, + fml::WeakPtr io_manager, + fml::RefPtr unref_queue, + fml::WeakPtr snapshot_delegate, + std::shared_ptr volatile_path_tracker) { + return std::make_unique(delegate, // + dispatcher_maker, // + vm, // + isolate_snapshot, // + task_runners, // + platform_data, // + settings, // + std::move(animator), // + io_manager, // + unref_queue, // + snapshot_delegate, // + volatile_path_tracker); +} +} // namespace + std::unique_ptr Shell::CreateShellOnPlatformThread( DartVMRef vm, TaskRunners task_runners, @@ -47,7 +75,8 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, - const Shell::CreateCallback& on_create_rasterizer) { + const Shell::CreateCallback& on_create_rasterizer, + const Shell::EngineCreateCallback& on_create_engine) { if (!task_runners.IsValid()) { FML_LOG(ERROR) << "Task runners to run the shell were invalid."; return nullptr; @@ -142,8 +171,8 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( vsync_waiter = std::move(vsync_waiter), // &weak_io_manager_future, // &snapshot_delegate_future, // - &unref_queue_future // - ]() mutable { + &unref_queue_future, // + &on_create_engine]() mutable { TRACE_EVENT0("flutter", "ShellSetupUISubsystem"); const auto& task_runners = shell->GetTaskRunners(); @@ -152,20 +181,19 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( auto animator = std::make_unique(*shell, task_runners, std::move(vsync_waiter)); - engine_promise.set_value(std::make_unique( - *shell, // - dispatcher_maker, // - *shell->GetDartVM(), // - std::move(isolate_snapshot), // - task_runners, // - platform_data, // - shell->GetSettings(), // - std::move(animator), // - weak_io_manager_future.get(), // - unref_queue_future.get(), // - snapshot_delegate_future.get(), // - shell->volatile_path_tracker_ // - )); + engine_promise.set_value( + on_create_engine(*shell, // + dispatcher_maker, // + *shell->GetDartVM(), // + std::move(isolate_snapshot), // + task_runners, // + platform_data, // + shell->GetSettings(), // + std::move(animator), // + weak_io_manager_future.get(), // + unref_queue_future.get(), // + snapshot_delegate_future.get(), // + shell->volatile_path_tracker_)); })); if (!shell->Setup(std::move(platform_view), // @@ -265,14 +293,40 @@ std::unique_ptr Shell::Create( TRACE_EVENT0("flutter", "Shell::Create"); + auto vm = 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(platform_data), // + std::move(settings), // + vm_data->GetIsolateSnapshot(), // isolate snapshot + on_create_platform_view, // + on_create_rasterizer, // + std::move(vm), // + CreateEngine); +} + +std::unique_ptr Shell::Create( + TaskRunners task_runners, + const PlatformData platform_data, + Settings settings, + fml::RefPtr isolate_snapshot, + const Shell::CreateCallback& on_create_platform_view, + const Shell::CreateCallback& on_create_rasterizer, + DartVMRef vm, + const Shell::EngineCreateCallback& on_create_engine) { + PerformInitializationTasks(settings); + PersistentCache::SetCacheSkSL(settings.cache_sksl); + + TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots"); + if (!task_runners.IsValid() || !on_create_platform_view || !on_create_rasterizer) { return nullptr; } - auto vm = DartVMRef::Create(settings); - FML_CHECK(vm) << "Must be able to initialize the VM."; - fml::AutoResetWaitableEvent latch; std::unique_ptr shell; fml::TaskRunner::RunNowOrPostTask( @@ -284,8 +338,8 @@ std::unique_ptr Shell::Create( platform_data, // settings, // on_create_platform_view, // - on_create_rasterizer // - ]() mutable { + on_create_rasterizer, // + &on_create_engine]() mutable { auto isolate_snapshot = vm->GetVMData()->GetIsolateSnapshot(); shell = CreateShellOnPlatformThread(std::move(vm), std::move(task_runners), // @@ -293,8 +347,8 @@ std::unique_ptr Shell::Create( settings, // std::move(isolate_snapshot), // on_create_platform_view, // - on_create_rasterizer // - ); + on_create_rasterizer, // + on_create_engine); latch.Signal(); })); latch.Wait(); @@ -423,14 +477,29 @@ Shell::~Shell() { std::unique_ptr Shell::Spawn( Settings settings, const CreateCallback& on_create_platform_view, - const CreateCallback& on_create_rasterizer) { + const CreateCallback& on_create_rasterizer) const { + FML_DCHECK(task_runners_.IsValid()); + std::unique_ptr result(Shell::Create( + task_runners_, PlatformData{}, settings, + vm_->GetVMData()->GetIsolateSnapshot(), on_create_platform_view, + on_create_rasterizer, vm_, + [engine = this->engine_.get()]( + Engine::Delegate& delegate, + const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm, + fml::RefPtr isolate_snapshot, + TaskRunners task_runners, const PlatformData platform_data, + Settings settings, std::unique_ptr animator, + fml::WeakPtr io_manager, + fml::RefPtr unref_queue, + fml::WeakPtr snapshot_delegate, + std::shared_ptr volatile_path_tracker) { + return engine->Spawn(/*delegate=*/delegate, + /*dispatcher_maker=*/dispatcher_maker, + /*settings=*/settings, + /*animator=*/std::move(animator)); + })); RunConfiguration configuration = RunConfiguration::InferFromSettings(settings); - TaskRunners task_runners = task_runners_; - FML_DCHECK(task_runners.IsValid()); - std::unique_ptr result(Shell::Create(std::move(task_runners), settings, - on_create_platform_view, - on_create_rasterizer)); result->RunEngine(std::move(configuration)); return result; } diff --git a/shell/common/shell.h b/shell/common/shell.h index 21214f0013f34..53017b08e3bea 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -98,6 +98,20 @@ class Shell final : public PlatformView::Delegate, public: template using CreateCallback = std::function(Shell&)>; + typedef std::function( + Engine::Delegate& delegate, + const PointerDataDispatcherMaker& dispatcher_maker, + DartVM& vm, + fml::RefPtr isolate_snapshot, + TaskRunners task_runners, + const PlatformData platform_data, + Settings settings, + std::unique_ptr animator, + fml::WeakPtr io_manager, + fml::RefPtr unref_queue, + fml::WeakPtr snapshot_delegate, + std::shared_ptr volatile_path_tracker)> + EngineCreateCallback; //---------------------------------------------------------------------------- /// @brief Creates a shell instance using the provided settings. The @@ -169,6 +183,27 @@ class Shell final : public PlatformView::Delegate, CreateCallback on_create_platform_view, CreateCallback on_create_rasterizer); + //---------------------------------------------------------------------------- + /// @brief Creates a shell instance using the provided settings. + /// @details This version of Create can take in a running DartVMRef and a + /// function that defines how the Shell's Engine should be + /// created. + /// @param[in] vm A running DartVMRef where this Shell's Dart + /// code will be executed. + /// @param[in] on_create_engine A function that creates an Engine during + /// initialization. + /// @see Shell::Create + /// + static std::unique_ptr Create( + TaskRunners task_runners, + const PlatformData platform_data, + Settings settings, + fml::RefPtr isolate_snapshot, + const CreateCallback& on_create_platform_view, + const CreateCallback& on_create_rasterizer, + DartVMRef vm, + const EngineCreateCallback& on_create_engine); + //---------------------------------------------------------------------------- /// @brief Destroys the shell. This is a synchronous operation and /// synchronous barrier blocks are introduced on the various @@ -188,7 +223,7 @@ class Shell final : public PlatformView::Delegate, std::unique_ptr Spawn( Settings settings, const CreateCallback& on_create_platform_view, - const CreateCallback& on_create_rasterizer); + const CreateCallback& on_create_rasterizer) const; //---------------------------------------------------------------------------- /// @brief Starts an isolate for the given RunConfiguration. @@ -429,7 +464,8 @@ class Shell final : public PlatformView::Delegate, Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, - const Shell::CreateCallback& on_create_rasterizer); + const Shell::CreateCallback& on_create_rasterizer, + const EngineCreateCallback& on_create_engine); bool Setup(std::unique_ptr platform_view, std::unique_ptr engine, diff --git a/third_party/tonic/dart_state.h b/third_party/tonic/dart_state.h index 1984a66bfb888..19dd9a5aee3c2 100644 --- a/third_party/tonic/dart_state.h +++ b/third_party/tonic/dart_state.h @@ -78,6 +78,9 @@ class DartState : public std::enable_shared_from_this { Dart_Handle library, Dart_Handle url); + protected: + Dart_Isolate isolate() const { return isolate_; } + private: Dart_Isolate isolate_; DartPersistentValue private_constructor_name_;