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

Commit e6620dd

Browse files
authored
Provide dart vm initalize isolate callback so that children isolates belong to parent's isolate group. (#9888)
* Provide dart vm initalize isolate callback so that children isolates belong to parent's isolate group. Without this callback each child isolate is created as a separate isolate group, and Dart VM won't be able to provide performance savings for spawning of those.
1 parent e2810dc commit e6620dd

File tree

3 files changed

+173
-45
lines changed

3 files changed

+173
-45
lines changed

runtime/dart_isolate.cc

Lines changed: 139 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
6666
advisory_script_entrypoint, // advisory entrypoint
6767
nullptr, // child isolate preparer
6868
isolate_create_callback, // isolate create callback
69-
isolate_shutdown_callback // isolate shutdown callback
69+
isolate_shutdown_callback, // isolate shutdown callback,
70+
true, // is_root_isolate
71+
true // is_group_root_isolate
7072
));
7173

7274
std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair(
@@ -110,7 +112,9 @@ DartIsolate::DartIsolate(const Settings& settings,
110112
std::string advisory_script_entrypoint,
111113
ChildIsolatePreparer child_isolate_preparer,
112114
fml::closure isolate_create_callback,
113-
fml::closure isolate_shutdown_callback)
115+
fml::closure isolate_shutdown_callback,
116+
bool is_root_isolate,
117+
bool is_group_root_isolate)
114118
: UIDartState(std::move(task_runners),
115119
settings.task_observer_add,
116120
settings.task_observer_remove,
@@ -126,7 +130,9 @@ DartIsolate::DartIsolate(const Settings& settings,
126130
shared_snapshot_(std::move(shared_snapshot)),
127131
child_isolate_preparer_(std::move(child_isolate_preparer)),
128132
isolate_create_callback_(isolate_create_callback),
129-
isolate_shutdown_callback_(isolate_shutdown_callback) {
133+
isolate_shutdown_callback_(isolate_shutdown_callback),
134+
is_root_isolate_(is_root_isolate),
135+
is_group_root_isolate_(is_group_root_isolate) {
130136
FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot.";
131137
phase_ = Phase::Uninitialized;
132138
}
@@ -148,7 +154,7 @@ std::string DartIsolate::GetServiceId() {
148154
return service_id;
149155
}
150156

151-
bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
157+
bool DartIsolate::Initialize(Dart_Isolate dart_isolate) {
152158
TRACE_EVENT0("flutter", "DartIsolate::Initialize");
153159
if (phase_ != Phase::Uninitialized) {
154160
return false;
@@ -162,12 +168,6 @@ bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
162168
return false;
163169
}
164170

165-
auto* isolate_data = static_cast<std::shared_ptr<DartIsolate>*>(
166-
Dart_IsolateGroupData(dart_isolate));
167-
if (isolate_data->get() != this) {
168-
return false;
169-
}
170-
171171
// After this point, isolate scopes can be safely used.
172172
SetIsolate(dart_isolate);
173173

@@ -179,8 +179,7 @@ bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
179179

180180
tonic::DartIsolateScope scope(isolate());
181181

182-
SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner(),
183-
is_root_isolate);
182+
SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner());
184183

185184
if (tonic::LogIfError(
186185
Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))) {
@@ -200,9 +199,8 @@ fml::RefPtr<fml::TaskRunner> DartIsolate::GetMessageHandlingTaskRunner() const {
200199
}
201200

202201
void DartIsolate::SetMessageHandlingTaskRunner(
203-
fml::RefPtr<fml::TaskRunner> runner,
204-
bool is_root_isolate) {
205-
if (!is_root_isolate || !runner) {
202+
fml::RefPtr<fml::TaskRunner> runner) {
203+
if (!IsRootIsolate() || !runner) {
206204
return;
207205
}
208206

@@ -251,7 +249,7 @@ bool DartIsolate::UpdateThreadPoolNames() const {
251249
return true;
252250
}
253251

254-
bool DartIsolate::LoadLibraries(bool is_root_isolate) {
252+
bool DartIsolate::LoadLibraries() {
255253
TRACE_EVENT0("flutter", "DartIsolate::LoadLibraries");
256254
if (phase_ != Phase::Initialized) {
257255
return false;
@@ -261,11 +259,11 @@ bool DartIsolate::LoadLibraries(bool is_root_isolate) {
261259

262260
DartIO::InitForIsolate();
263261

264-
DartUI::InitForIsolate(is_root_isolate);
262+
DartUI::InitForIsolate(IsRootIsolate());
265263

266264
const bool is_service_isolate = Dart_IsServiceIsolate(isolate());
267265

268-
DartRuntimeHooks::Install(is_root_isolate && !is_service_isolate,
266+
DartRuntimeHooks::Install(IsRootIsolate() && !is_service_isolate,
269267
GetAdvisoryScriptURI());
270268

271269
if (!is_service_isolate) {
@@ -645,6 +643,7 @@ Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback(
645643
Dart_IsolateFlags* flags,
646644
std::shared_ptr<DartIsolate>* parent_embedder_isolate,
647645
char** error) {
646+
TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCreateCallback");
648647
if (parent_embedder_isolate == nullptr &&
649648
strcmp(advisory_script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
650649
// The VM attempts to start the VM service for us on |Dart_Initialize|. In
@@ -672,6 +671,58 @@ Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback(
672671
.first;
673672
}
674673

674+
// |Dart_IsolateInitializeCallback|
675+
bool DartIsolate::DartIsolateInitializeCallback(void** child_callback_data,
676+
char** error) {
677+
TRACE_EVENT0("flutter", "DartIsolate::DartIsolateInitializeCallback");
678+
Dart_Isolate isolate = Dart_CurrentIsolate();
679+
if (isolate == nullptr) {
680+
*error = strdup("Isolate should be available in initialize callback.");
681+
FML_DLOG(ERROR) << *error;
682+
return false;
683+
}
684+
685+
auto* root_embedder_isolate = static_cast<std::shared_ptr<DartIsolate>*>(
686+
Dart_CurrentIsolateGroupData());
687+
688+
TaskRunners null_task_runners(
689+
(*root_embedder_isolate)->GetAdvisoryScriptURI(),
690+
/* platform= */ nullptr, /* gpu= */ nullptr,
691+
/* ui= */ nullptr,
692+
/* io= */ nullptr);
693+
694+
auto embedder_isolate = std::make_unique<std::shared_ptr<DartIsolate>>(
695+
std::make_shared<DartIsolate>(
696+
(*root_embedder_isolate)->GetSettings(), // settings
697+
(*root_embedder_isolate)->GetIsolateSnapshot(), // isolate_snapshot
698+
(*root_embedder_isolate)->GetSharedSnapshot(), // shared_snapshot
699+
null_task_runners, // task_runners
700+
fml::WeakPtr<IOManager>{}, // io_manager
701+
fml::WeakPtr<ImageDecoder>{}, // io_manager
702+
(*root_embedder_isolate)
703+
->GetAdvisoryScriptURI(), // advisory_script_uri
704+
(*root_embedder_isolate)
705+
->GetAdvisoryScriptEntrypoint(), // advisory_script_entrypoint
706+
(*root_embedder_isolate)->child_isolate_preparer_, // preparer
707+
(*root_embedder_isolate)->isolate_create_callback_, // on create
708+
(*root_embedder_isolate)->isolate_shutdown_callback_, // on shutdown
709+
false, // is_root_isolate
710+
false)); // is_group_root_isolate
711+
712+
// root isolate should have been created via CreateRootIsolate and
713+
// CreateDartVMAndEmbedderObjectPair
714+
if (!InitializeIsolate(*embedder_isolate, isolate, error)) {
715+
return false;
716+
}
717+
718+
// The ownership of the embedder object is controlled by the Dart VM. So the
719+
// only reference returned to the caller is weak.
720+
*child_callback_data = embedder_isolate.release();
721+
722+
Dart_EnterIsolate(isolate);
723+
return true;
724+
}
725+
675726
std::pair<Dart_Isolate, std::weak_ptr<DartIsolate>>
676727
DartIsolate::CreateDartVMAndEmbedderObjectPair(
677728
const char* advisory_script_uri,
@@ -711,12 +762,11 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
711762
fml::WeakPtr<ImageDecoder>{}, // io_manager
712763
advisory_script_uri, // advisory_script_uri
713764
advisory_script_entrypoint, // advisory_script_entrypoint
714-
(*raw_embedder_isolate)->child_isolate_preparer_, // preparer
715-
(*raw_embedder_isolate)->isolate_create_callback_, // on create
716-
(*raw_embedder_isolate)->isolate_shutdown_callback_ // on shutdown
717-
)
718-
719-
);
765+
(*raw_embedder_isolate)->child_isolate_preparer_, // preparer
766+
(*raw_embedder_isolate)->isolate_create_callback_, // on create
767+
(*raw_embedder_isolate)->isolate_shutdown_callback_, // on shutdown
768+
is_root_isolate,
769+
true)); // is_root_group_isolate
720770
}
721771

722772
// Create the Dart VM isolate and give it the embedder object as the baton.
@@ -736,50 +786,100 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
736786
return {nullptr, {}};
737787
}
738788

739-
if (!(*embedder_isolate)->Initialize(isolate, is_root_isolate)) {
789+
if (!InitializeIsolate(*embedder_isolate, isolate, error)) {
790+
return {nullptr, {}};
791+
}
792+
793+
auto* isolate_data = static_cast<std::shared_ptr<DartIsolate>*>(
794+
Dart_IsolateGroupData(isolate));
795+
FML_DCHECK(isolate_data->get() == embedder_isolate->get());
796+
797+
auto weak_embedder_isolate = (*embedder_isolate)->GetWeakIsolatePtr();
798+
799+
// The ownership of the embedder object is controlled by the Dart VM. So the
800+
// only reference returned to the caller is weak.
801+
embedder_isolate.release();
802+
return {isolate, weak_embedder_isolate};
803+
}
804+
805+
bool DartIsolate::InitializeIsolate(
806+
std::shared_ptr<DartIsolate> embedder_isolate,
807+
Dart_Isolate isolate,
808+
char** error) {
809+
TRACE_EVENT0("flutter", "DartIsolate::InitializeIsolate");
810+
if (!embedder_isolate->Initialize(isolate)) {
740811
*error = strdup("Embedder could not initialize the Dart isolate.");
741812
FML_DLOG(ERROR) << *error;
742-
return {nullptr, {}};
813+
return false;
743814
}
744815

745-
if (!(*embedder_isolate)->LoadLibraries(is_root_isolate)) {
816+
if (!embedder_isolate->LoadLibraries()) {
746817
*error =
747818
strdup("Embedder could not load libraries in the new Dart isolate.");
748819
FML_DLOG(ERROR) << *error;
749-
return {nullptr, {}};
820+
return false;
750821
}
751822

752-
auto weak_embedder_isolate = (*embedder_isolate)->GetWeakIsolatePtr();
753-
754823
// Root isolates will be setup by the engine and the service isolate (which is
755824
// also a root isolate) by the utility routines in the VM. However, secondary
756825
// isolates will be run by the VM if they are marked as runnable.
757-
if (!is_root_isolate) {
758-
FML_DCHECK((*embedder_isolate)->child_isolate_preparer_);
759-
if (!(*embedder_isolate)
760-
->child_isolate_preparer_((*embedder_isolate).get())) {
826+
if (!embedder_isolate->IsRootIsolate()) {
827+
FML_DCHECK(embedder_isolate->child_isolate_preparer_);
828+
if (!embedder_isolate->child_isolate_preparer_(embedder_isolate.get())) {
761829
*error = strdup("Could not prepare the child isolate to run.");
762830
FML_DLOG(ERROR) << *error;
763-
return {nullptr, {}};
831+
return false;
764832
}
765833
}
766834

767-
// The ownership of the embedder object is controlled by the Dart VM. So the
768-
// only reference returned to the caller is weak.
769-
embedder_isolate.release();
770-
return {isolate, weak_embedder_isolate};
835+
return true;
771836
}
772837

773838
// |Dart_IsolateShutdownCallback|
774839
void DartIsolate::DartIsolateShutdownCallback(
775840
std::shared_ptr<DartIsolate>* isolate_group_data,
776841
std::shared_ptr<DartIsolate>* isolate_data) {
842+
TRACE_EVENT0("flutter", "DartIsolate::DartIsolateShutdownCallback");
777843
isolate_group_data->get()->OnShutdownCallback();
778844
}
779845

780846
// |Dart_IsolateGroupCleanupCallback|
781847
void DartIsolate::DartIsolateGroupCleanupCallback(
782848
std::shared_ptr<DartIsolate>* isolate_data) {
849+
TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCleanupCallback");
850+
FML_DLOG(INFO) << "DartIsolateGroupCleanupCallback isolate_data "
851+
<< isolate_data;
852+
853+
delete isolate_data;
854+
}
855+
856+
// |Dart_IsolateCleanupCallback|
857+
void DartIsolate::DartIsolateCleanupCallback(
858+
std::shared_ptr<DartIsolate>* isolate_group_data,
859+
std::shared_ptr<DartIsolate>* isolate_data) {
860+
TRACE_EVENT0("flutter", "DartIsolate::DartIsolateCleanupCallback");
861+
862+
if ((*isolate_data)->IsRootIsolate()) {
863+
// isolate_data will be cleaned up as part of IsolateGroup cleanup
864+
FML_DLOG(INFO)
865+
<< "DartIsolateCleanupCallback no-op for root isolate isolate_data "
866+
<< isolate_data;
867+
return;
868+
}
869+
if ((*isolate_data)->IsGroupRootIsolate()) {
870+
// Even if isolate was not a root isolate(i.e. was spawned),
871+
// it might have IsolateGroup created for it (when
872+
// --no-enable-isolate-groups dart vm flag is used).
873+
// Then its isolate_data will be cleaned up as part of IsolateGroup
874+
// cleanup as well.
875+
FML_DLOG(INFO) << "DartIsolateCleanupCallback no-op for group root isolate "
876+
"isolate_data "
877+
<< isolate_data;
878+
return;
879+
}
880+
881+
FML_DLOG(INFO) << "DartIsolateCleanupCallback cleaned up isolate_data "
882+
<< isolate_data;
783883
delete isolate_data;
784884
}
785885

runtime/dart_isolate.h

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ class DartIsolate : public UIDartState {
6464
std::string advisory_script_entrypoint,
6565
ChildIsolatePreparer child_isolate_preparer,
6666
fml::closure isolate_create_callback,
67-
fml::closure isolate_shutdown_callback);
67+
fml::closure isolate_shutdown_callback,
68+
bool is_root_isolate,
69+
bool is_group_root_isolate);
6870

6971
~DartIsolate() override;
7072

@@ -113,6 +115,13 @@ class DartIsolate : public UIDartState {
113115

114116
fml::RefPtr<fml::TaskRunner> GetMessageHandlingTaskRunner() const;
115117

118+
// Root isolate of the VM application
119+
bool IsRootIsolate() const { return is_root_isolate_; }
120+
// Isolate that owns IsolateGroup it lives in.
121+
// When --no-enable-isolate-groups dart vm flag is set,
122+
// all child isolates will have their own IsolateGroups.
123+
bool IsGroupRootIsolate() const { return is_group_root_isolate_; }
124+
116125
private:
117126
bool LoadKernel(std::shared_ptr<const fml::Mapping> mapping, bool last_piece);
118127

@@ -139,14 +148,15 @@ class DartIsolate : public UIDartState {
139148
const fml::closure isolate_create_callback_;
140149
const fml::closure isolate_shutdown_callback_;
141150

142-
FML_WARN_UNUSED_RESULT bool Initialize(Dart_Isolate isolate,
143-
bool is_root_isolate);
151+
const bool is_root_isolate_;
152+
const bool is_group_root_isolate_;
153+
154+
FML_WARN_UNUSED_RESULT bool Initialize(Dart_Isolate isolate);
144155

145-
void SetMessageHandlingTaskRunner(fml::RefPtr<fml::TaskRunner> runner,
146-
bool is_root_isolate);
156+
void SetMessageHandlingTaskRunner(fml::RefPtr<fml::TaskRunner> runner);
147157

148158
FML_WARN_UNUSED_RESULT
149-
bool LoadLibraries(bool is_root_isolate);
159+
bool LoadLibraries();
150160

151161
bool UpdateThreadPoolNames() const;
152162

@@ -165,6 +175,10 @@ class DartIsolate : public UIDartState {
165175
std::shared_ptr<DartIsolate>* embedder_isolate,
166176
char** error);
167177

178+
// |Dart_IsolateInitializeCallback|
179+
static bool DartIsolateInitializeCallback(void** child_callback_data,
180+
char** error);
181+
168182
static Dart_Isolate DartCreateAndStartServiceIsolate(
169183
const char* package_root,
170184
const char* package_config,
@@ -183,11 +197,20 @@ class DartIsolate : public UIDartState {
183197
bool is_root_isolate,
184198
char** error);
185199

200+
static bool InitializeIsolate(std::shared_ptr<DartIsolate> embedder_isolate,
201+
Dart_Isolate isolate,
202+
char** error);
203+
186204
// |Dart_IsolateShutdownCallback|
187205
static void DartIsolateShutdownCallback(
188206
std::shared_ptr<DartIsolate>* isolate_group_data,
189207
std::shared_ptr<DartIsolate>* isolate_data);
190208

209+
// |Dart_IsolateCleanupCallback|
210+
static void DartIsolateCleanupCallback(
211+
std::shared_ptr<DartIsolate>* isolate_group_data,
212+
std::shared_ptr<DartIsolate>* isolate_data);
213+
191214
// |Dart_IsolateGroupCleanupCallback|
192215
static void DartIsolateGroupCleanupCallback(
193216
std::shared_ptr<DartIsolate>* isolate_group_data);

runtime/dart_vm.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,14 @@ DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
395395
vm_data_->GetVMSnapshot().GetInstructionsMapping();
396396
params.create_group = reinterpret_cast<decltype(params.create_group)>(
397397
DartIsolate::DartIsolateGroupCreateCallback);
398+
params.initialize_isolate =
399+
reinterpret_cast<decltype(params.initialize_isolate)>(
400+
DartIsolate::DartIsolateInitializeCallback);
398401
params.shutdown_isolate =
399402
reinterpret_cast<decltype(params.shutdown_isolate)>(
400403
DartIsolate::DartIsolateShutdownCallback);
404+
params.cleanup_isolate = reinterpret_cast<decltype(params.cleanup_isolate)>(
405+
DartIsolate::DartIsolateCleanupCallback);
401406
params.cleanup_group = reinterpret_cast<decltype(params.cleanup_group)>(
402407
DartIsolate::DartIsolateGroupCleanupCallback);
403408
params.thread_exit = ThreadExitCallback;

0 commit comments

Comments
 (0)