Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit bcab97d

Browse files
committed
Create root isolate asynchronously
1 parent 94f5cf4 commit bcab97d

File tree

8 files changed

+136
-53
lines changed

8 files changed

+136
-53
lines changed

runtime/runtime_controller.cc

Lines changed: 89 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ namespace flutter {
1818

1919
RuntimeController::RuntimeController(RuntimeDelegate& client,
2020
TaskRunners p_task_runners)
21-
: client_(client), vm_(nullptr), task_runners_(p_task_runners) {}
21+
: client_(client),
22+
vm_(nullptr),
23+
task_runners_(p_task_runners),
24+
weak_factory_(this) {}
2225

2326
RuntimeController::RuntimeController(
2427
RuntimeDelegate& p_client,
@@ -50,48 +53,76 @@ RuntimeController::RuntimeController(
5053
platform_data_(std::move(p_platform_data)),
5154
isolate_create_callback_(p_isolate_create_callback),
5255
isolate_shutdown_callback_(p_isolate_shutdown_callback),
53-
persistent_isolate_data_(std::move(p_persistent_isolate_data)) {
54-
// Create the root isolate as soon as the runtime controller is initialized.
56+
persistent_isolate_data_(std::move(p_persistent_isolate_data)),
57+
weak_factory_(this) {
58+
// Create the root isolate as soon as the runtime controller is initialized,
59+
// but not using a synchronous way to avoid blocking the platform thread a
60+
// long time as it is waiting while creating `Shell` on that platform thread.
5561
// It will be run at a later point when the engine provides a run
5662
// configuration and then runs the isolate.
57-
auto strong_root_isolate =
58-
DartIsolate::CreateRootIsolate(
59-
vm_->GetVMData()->GetSettings(), //
60-
isolate_snapshot_, //
61-
task_runners_, //
62-
std::make_unique<PlatformConfiguration>(this), //
63-
snapshot_delegate_, //
64-
io_manager_, //
65-
unref_queue_, //
66-
image_decoder_, //
67-
p_advisory_script_uri, //
68-
p_advisory_script_entrypoint, //
69-
nullptr, //
70-
isolate_create_callback_, //
71-
isolate_shutdown_callback_ //
72-
)
73-
.lock();
74-
75-
FML_CHECK(strong_root_isolate) << "Could not create root isolate.";
76-
77-
// The root isolate ivar is weak.
78-
root_isolate_ = strong_root_isolate;
79-
80-
strong_root_isolate->SetReturnCodeCallback([this](uint32_t code) {
81-
root_isolate_return_code_ = {true, code};
82-
});
83-
84-
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
85-
tonic::DartState::Scope scope(strong_root_isolate);
86-
platform_configuration->DidCreateIsolate();
87-
if (!FlushRuntimeStateToIsolate()) {
88-
FML_DLOG(ERROR) << "Could not setup initial isolate state.";
89-
}
90-
} else {
91-
FML_DCHECK(false) << "RuntimeController created without window binding.";
92-
}
93-
94-
FML_DCHECK(Dart_CurrentIsolate() == nullptr);
63+
create_and_config_root_isolate_ =
64+
std::async(std::launch::deferred, [self = weak_factory_.GetWeakPtr()]() {
65+
if (!self) {
66+
return;
67+
}
68+
69+
auto strong_root_isolate =
70+
DartIsolate::CreateRootIsolate(
71+
self->vm_->GetVMData()->GetSettings(), //
72+
self->isolate_snapshot_, //
73+
self->task_runners_, //
74+
std::make_unique<PlatformConfiguration>(self.get()), //
75+
self->snapshot_delegate_, //
76+
self->io_manager_, //
77+
self->unref_queue_, //
78+
self->image_decoder_, //
79+
self->advisory_script_uri_, //
80+
self->advisory_script_entrypoint_, //
81+
nullptr, //
82+
self->isolate_create_callback_, //
83+
self->isolate_shutdown_callback_ //
84+
)
85+
.lock();
86+
87+
FML_CHECK(strong_root_isolate) << "Could not create root isolate.";
88+
89+
// The root isolate ivar is weak.
90+
self->root_isolate_ = strong_root_isolate;
91+
92+
strong_root_isolate->SetReturnCodeCallback([self](uint32_t code) {
93+
if (!self) {
94+
return;
95+
}
96+
97+
self->root_isolate_return_code_ = {true, code};
98+
});
99+
100+
if (auto* platform_configuration =
101+
self->GetPlatformConfigurationIfAvailable()) {
102+
tonic::DartState::Scope scope(strong_root_isolate);
103+
platform_configuration->DidCreateIsolate();
104+
if (!self->FlushRuntimeStateToIsolate()) {
105+
FML_DLOG(ERROR) << "Could not setup initial isolate state.";
106+
}
107+
} else {
108+
FML_DCHECK(false)
109+
<< "RuntimeController created without window binding.";
110+
}
111+
112+
FML_DCHECK(Dart_CurrentIsolate() == nullptr);
113+
114+
self->client_.OnRootIsolateCreated();
115+
return;
116+
});
117+
118+
task_runners_.GetUITaskRunner()->PostTask(
119+
[self = weak_factory_.GetWeakPtr()]() {
120+
if (!self) {
121+
return;
122+
}
123+
124+
self->GetRootIsolate();
125+
});
95126
}
96127

97128
RuntimeController::~RuntimeController() {
@@ -107,8 +138,8 @@ RuntimeController::~RuntimeController() {
107138
}
108139
}
109140

110-
bool RuntimeController::IsRootIsolateRunning() const {
111-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
141+
bool RuntimeController::IsRootIsolateRunning() {
142+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
112143
if (root_isolate) {
113144
return root_isolate->GetPhase() == DartIsolate::Phase::Running;
114145
}
@@ -234,7 +265,7 @@ bool RuntimeController::ReportTimings(std::vector<int64_t> timings) {
234265
}
235266

236267
bool RuntimeController::NotifyIdle(int64_t deadline) {
237-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
268+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
238269
if (!root_isolate) {
239270
return false;
240271
}
@@ -291,7 +322,7 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id,
291322

292323
PlatformConfiguration*
293324
RuntimeController::GetPlatformConfigurationIfAvailable() {
294-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
325+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
295326
return root_isolate ? root_isolate->platform_configuration() : nullptr;
296327
}
297328

@@ -353,17 +384,17 @@ RuntimeController::ComputePlatformResolvedLocale(
353384
}
354385

355386
Dart_Port RuntimeController::GetMainPort() {
356-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
387+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
357388
return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT;
358389
}
359390

360391
std::string RuntimeController::GetIsolateName() {
361-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
392+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
362393
return root_isolate ? root_isolate->debug_name() : "";
363394
}
364395

365396
bool RuntimeController::HasLivePorts() {
366-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
397+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
367398
if (!root_isolate) {
368399
return false;
369400
}
@@ -372,11 +403,20 @@ bool RuntimeController::HasLivePorts() {
372403
}
373404

374405
tonic::DartErrorHandleType RuntimeController::GetLastError() {
375-
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
406+
std::shared_ptr<DartIsolate> root_isolate = GetRootIsolate().lock();
376407
return root_isolate ? root_isolate->GetLastError() : tonic::kNoError;
377408
}
378409

379410
std::weak_ptr<DartIsolate> RuntimeController::GetRootIsolate() {
411+
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
412+
if (root_isolate) {
413+
return root_isolate_;
414+
}
415+
416+
// Root isolate is not yet created, get it and do some configuration.
417+
FML_DCHECK(create_and_config_root_isolate_.valid());
418+
create_and_config_root_isolate_.get();
419+
380420
return root_isolate_;
381421
}
382422

runtime/runtime_controller.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
66
#define FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
77

8+
#include <future>
89
#include <memory>
910
#include <vector>
1011

@@ -340,7 +341,7 @@ class RuntimeController : public PlatformConfigurationClient {
340341
///
341342
/// @return True if root isolate running, False otherwise.
342343
///
343-
virtual bool IsRootIsolateRunning() const;
344+
virtual bool IsRootIsolateRunning();
344345

345346
//----------------------------------------------------------------------------
346347
/// @brief Dispatch the specified platform message to running root
@@ -471,11 +472,13 @@ class RuntimeController : public PlatformConfigurationClient {
471472
std::string advisory_script_entrypoint_;
472473
std::function<void(int64_t)> idle_notification_callback_;
473474
PlatformData platform_data_;
475+
std::future<void> create_and_config_root_isolate_;
474476
std::weak_ptr<DartIsolate> root_isolate_;
475477
std::pair<bool, uint32_t> root_isolate_return_code_ = {false, 0};
476478
const fml::closure isolate_create_callback_;
477479
const fml::closure isolate_shutdown_callback_;
478480
std::shared_ptr<const fml::Mapping> persistent_isolate_data_;
481+
fml::WeakPtrFactory<RuntimeController> weak_factory_;
479482

480483
PlatformConfiguration* GetPlatformConfigurationIfAvailable();
481484

runtime/runtime_delegate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class RuntimeDelegate {
3232

3333
virtual FontCollection& GetFontCollection() = 0;
3434

35+
virtual void OnRootIsolateCreated() = 0;
36+
3537
virtual void UpdateIsolateDescription(const std::string isolate_name,
3638
int64_t isolate_port) = 0;
3739

shell/common/engine.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
497497
}
498498
}
499499

500+
void Engine::OnRootIsolateCreated() {
501+
delegate_.OnRootIsolateCreated();
502+
}
503+
500504
void Engine::UpdateIsolateDescription(const std::string isolate_name,
501505
int64_t isolate_port) {
502506
delegate_.UpdateIsolateDescription(isolate_name, isolate_port);

shell/common/engine.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
185185
///
186186
virtual void OnPreEngineRestart() = 0;
187187

188+
//--------------------------------------------------------------------------
189+
/// @brief Notifies the shell that the root isolate is created.
190+
/// Currently, this information is to add to the service
191+
/// protocol list of available root isolates running in the VM
192+
/// and their names so that the appropriate isolate can be
193+
/// selected in the tools for debugging and instrumentation.
194+
///
195+
virtual void OnRootIsolateCreated() = 0;
196+
188197
//--------------------------------------------------------------------------
189198
/// @brief Notifies the shell of the name of the root isolate and its
190199
/// port when that isolate is launched, restarted (in the
@@ -812,6 +821,9 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
812821
// |RuntimeDelegate|
813822
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override;
814823

824+
// |RuntimeDelegate|
825+
void OnRootIsolateCreated() override;
826+
815827
// |RuntimeDelegate|
816828
void UpdateIsolateDescription(const std::string isolate_name,
817829
int64_t isolate_port) override;

shell/common/engine_unittests.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class MockDelegate : public Engine::Delegate {
2424
MOCK_METHOD1(OnEngineHandlePlatformMessage,
2525
void(fml::RefPtr<PlatformMessage>));
2626
MOCK_METHOD0(OnPreEngineRestart, void());
27+
MOCK_METHOD0(OnRootIsolateCreated, void());
2728
MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t));
2829
MOCK_METHOD1(SetNeedsReportTimings, void(bool));
2930
MOCK_METHOD1(ComputePlatformResolvedLocale,
@@ -46,6 +47,7 @@ class MockRuntimeDelegate : public RuntimeDelegate {
4647
void(SemanticsNodeUpdates, CustomAccessibilityActionUpdates));
4748
MOCK_METHOD1(HandlePlatformMessage, void(fml::RefPtr<PlatformMessage>));
4849
MOCK_METHOD0(GetFontCollection, FontCollection&());
50+
MOCK_METHOD0(OnRootIsolateCreated, void());
4951
MOCK_METHOD2(UpdateIsolateDescription, void(const std::string, int64_t));
5052
MOCK_METHOD1(SetNeedsReportTimings, void(bool));
5153
MOCK_METHOD1(ComputePlatformResolvedLocale,
@@ -57,7 +59,7 @@ class MockRuntimeController : public RuntimeController {
5759
public:
5860
MockRuntimeController(RuntimeDelegate& client, TaskRunners p_task_runners)
5961
: RuntimeController(client, p_task_runners) {}
60-
MOCK_CONST_METHOD0(IsRootIsolateRunning, bool());
62+
MOCK_METHOD0(IsRootIsolateRunning, bool());
6163
MOCK_METHOD1(DispatchPlatformMessage, bool(fml::RefPtr<PlatformMessage>));
6264
};
6365

shell/common/shell.cc

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,6 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
558558

559559
is_setup_ = true;
560560

561-
vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());
562-
563561
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
564562
task_runners_.GetIOTaskRunner());
565563

@@ -1097,6 +1095,19 @@ void Shell::OnPreEngineRestart() {
10971095
latch.Wait();
10981096
}
10991097

1098+
// |Engine::Delegate|
1099+
void Shell::OnRootIsolateCreated() {
1100+
auto description = GetServiceProtocolDescription();
1101+
fml::TaskRunner::RunNowOrPostTask(
1102+
task_runners_.GetPlatformTaskRunner(),
1103+
[self = weak_factory_.GetWeakPtr(),
1104+
description = std::move(description)]() {
1105+
if (self) {
1106+
self->vm_->GetServiceProtocol()->AddHandler(self.get(), description);
1107+
}
1108+
});
1109+
}
1110+
11001111
// |Engine::Delegate|
11011112
void Shell::UpdateIsolateDescription(const std::string isolate_name,
11021113
int64_t isolate_port) {
@@ -1241,6 +1252,12 @@ bool Shell::HandleServiceProtocolMessage(
12411252
// |ServiceProtocol::Handler|
12421253
ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription()
12431254
const {
1255+
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
1256+
1257+
if (!engine_) {
1258+
return ServiceProtocol::Handler::Description();
1259+
}
1260+
12441261
return {
12451262
engine_->GetUIIsolateMainPort(),
12461263
engine_->GetUIIsolateName(),

shell/common/shell.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ class Shell final : public PlatformView::Delegate,
513513
// |Engine::Delegate|
514514
void OnPreEngineRestart() override;
515515

516+
// |Engine::Delegate|
517+
void OnRootIsolateCreated() override;
518+
516519
// |Engine::Delegate|
517520
void UpdateIsolateDescription(const std::string isolate_name,
518521
int64_t isolate_port) override;

0 commit comments

Comments
 (0)