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

Commit 09d05a3

Browse files
authored
Prepare and run child isolates on a VM managed (i.e. no UI) task runner. (#5054)
1 parent adee351 commit 09d05a3

File tree

2 files changed

+70
-25
lines changed

2 files changed

+70
-25
lines changed

runtime/dart_isolate.cc

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ fml::WeakPtr<DartIsolate> DartIsolate::CreateRootIsolate(
5757
std::move(resource_context), // resource context
5858
std::move(unref_queue), // skia unref queue
5959
advisory_script_uri, // advisory URI
60-
advisory_script_entrypoint // advisory entrypoint
60+
advisory_script_entrypoint, // advisory entrypoint
61+
nullptr // child isolate preparer will be set when this isolate is
62+
// prepared to run
6163
);
6264

6365
std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair(
@@ -85,6 +87,8 @@ fml::WeakPtr<DartIsolate> DartIsolate::CreateRootIsolate(
8587
embedder_isolate->set_use_blink(vm->GetSettings().using_blink);
8688
}
8789

90+
root_embedder_data.release();
91+
8892
return embedder_isolate;
8993
}
9094

@@ -94,7 +98,8 @@ DartIsolate::DartIsolate(const DartVM* vm,
9498
fml::WeakPtr<GrContext> resource_context,
9599
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
96100
std::string advisory_script_uri,
97-
std::string advisory_script_entrypoint)
101+
std::string advisory_script_entrypoint,
102+
ChildIsolatePreparer child_isolate_preparer)
98103
: UIDartState(std::move(task_runners),
99104
vm->GetSettings().task_observer_add,
100105
vm->GetSettings().task_observer_remove,
@@ -105,6 +110,7 @@ DartIsolate::DartIsolate(const DartVM* vm,
105110
vm->GetSettings().log_tag),
106111
vm_(vm),
107112
isolate_snapshot_(std::move(isolate_snapshot)),
113+
child_isolate_preparer_(std::move(child_isolate_preparer)),
108114
weak_factory_(std::make_unique<fml::WeakPtrFactory<DartIsolate>>(this)) {
109115
FXL_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot.";
110116

@@ -262,19 +268,22 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() {
262268
return false;
263269
}
264270

271+
child_isolate_preparer_ = [](DartIsolate* isolate) {
272+
return isolate->PrepareForRunningFromPrecompiledCode();
273+
};
265274
phase_ = Phase::Ready;
266275
return true;
267276
}
268277

269-
static bool LoadScriptSnapshot(std::unique_ptr<fml::Mapping> mapping) {
278+
static bool LoadScriptSnapshot(std::shared_ptr<const fml::Mapping> mapping) {
270279
if (tonic::LogIfError(Dart_LoadScriptFromSnapshot(mapping->GetMapping(),
271280
mapping->GetSize()))) {
272281
return false;
273282
}
274283
return true;
275284
}
276285

277-
static bool LoadKernelSnapshot(std::unique_ptr<fml::Mapping> mapping) {
286+
static bool LoadKernelSnapshot(std::shared_ptr<const fml::Mapping> mapping) {
278287
if (tonic::LogIfError(Dart_LoadScriptFromKernel(mapping->GetMapping(),
279288
mapping->GetSize()))) {
280289
return false;
@@ -283,7 +292,7 @@ static bool LoadKernelSnapshot(std::unique_ptr<fml::Mapping> mapping) {
283292
return true;
284293
}
285294

286-
static bool LoadSnapshot(std::unique_ptr<fml::Mapping> mapping,
295+
static bool LoadSnapshot(std::shared_ptr<const fml::Mapping> mapping,
287296
bool is_kernel) {
288297
if (is_kernel) {
289298
return LoadKernelSnapshot(std::move(mapping));
@@ -295,7 +304,7 @@ static bool LoadSnapshot(std::unique_ptr<fml::Mapping> mapping,
295304

296305
FXL_WARN_UNUSED_RESULT
297306
bool DartIsolate::PrepareForRunningFromSnapshot(
298-
std::unique_ptr<fml::Mapping> mapping) {
307+
std::shared_ptr<const fml::Mapping> mapping) {
299308
TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSnapshot");
300309
if (phase_ != Phase::LibrariesSetup) {
301310
return false;
@@ -315,7 +324,7 @@ bool DartIsolate::PrepareForRunningFromSnapshot(
315324
return false;
316325
}
317326

318-
if (!LoadSnapshot(std::move(mapping), vm_->GetPlatformKernel() != nullptr)) {
327+
if (!LoadSnapshot(mapping, vm_->GetPlatformKernel() != nullptr)) {
319328
return false;
320329
}
321330

@@ -327,6 +336,9 @@ bool DartIsolate::PrepareForRunningFromSnapshot(
327336
return false;
328337
}
329338

339+
child_isolate_preparer_ = [mapping](DartIsolate* isolate) {
340+
return isolate->PrepareForRunningFromSnapshot(mapping);
341+
};
330342
phase_ = Phase::Ready;
331343
return true;
332344
}
@@ -378,6 +390,9 @@ bool DartIsolate::PrepareForRunningFromSource(
378390
return false;
379391
}
380392

393+
child_isolate_preparer_ = [main_source_file, packages](DartIsolate* isolate) {
394+
return isolate->PrepareForRunningFromSource(main_source_file, packages);
395+
};
381396
phase_ = Phase::Ready;
382397
return true;
383398
}
@@ -438,6 +453,7 @@ bool DartIsolate::Run(const std::string& entrypoint_name) {
438453
}
439454

440455
phase_ = Phase::Running;
456+
FXL_DLOG(INFO) << "New isolate is in the running state.";
441457
return true;
442458
}
443459

@@ -592,31 +608,39 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
592608
const char* package_root,
593609
const char* package_config,
594610
Dart_IsolateFlags* flags,
595-
DartIsolate* parent_embedder_isolate,
611+
DartIsolate* p_parent_embedder_isolate,
596612
bool is_root_isolate,
597613
char** error) {
598614
TRACE_EVENT0("flutter", "DartIsolate::CreateDartVMAndEmbedderObjectPair");
599-
if (parent_embedder_isolate == nullptr ||
600-
parent_embedder_isolate->GetDartVM() == nullptr) {
615+
616+
std::unique_ptr<DartIsolate> embedder_isolate{p_parent_embedder_isolate};
617+
618+
if (embedder_isolate == nullptr || embedder_isolate->GetDartVM() == nullptr) {
601619
*error =
602620
strdup("Parent isolate did not have embedder specific callback data.");
603621
FXL_DLOG(ERROR) << *error;
604622
return {nullptr, {}};
605623
}
606624

607-
const DartVM* vm = parent_embedder_isolate->GetDartVM();
625+
const DartVM* vm = embedder_isolate->GetDartVM();
608626

609-
// Create the native object on the embedder side. This object is deleted in
610-
// the cleanup callback.
611-
auto embedder_isolate = std::make_unique<DartIsolate>(
612-
vm, //
613-
parent_embedder_isolate->GetIsolateSnapshot(), //
614-
parent_embedder_isolate->GetTaskRunners(), //
615-
parent_embedder_isolate->GetResourceContext(), //
616-
parent_embedder_isolate->GetSkiaUnrefQueue(), //
617-
advisory_script_uri, //
618-
advisory_script_entrypoint //
619-
);
627+
if (!is_root_isolate) {
628+
auto raw_embedder_isolate = embedder_isolate.release();
629+
630+
blink::TaskRunners null_task_runners(advisory_script_uri, nullptr, nullptr,
631+
nullptr, nullptr);
632+
633+
embedder_isolate = std::make_unique<DartIsolate>(
634+
vm, // vm
635+
raw_embedder_isolate->GetIsolateSnapshot(), // isolate_snapshot
636+
null_task_runners, // task_runners
637+
fml::WeakPtr<GrContext>{}, // resource_context
638+
nullptr, // unref_queue
639+
advisory_script_uri, // advisory_script_uri
640+
advisory_script_entrypoint, // advisory_script_entrypoint
641+
raw_embedder_isolate->child_isolate_preparer_ // child isolate preparer
642+
);
643+
}
620644

621645
// Create the Dart VM isolate and give it the embedder object as the baton.
622646
Dart_Isolate isolate =
@@ -658,9 +682,25 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
658682
return {nullptr, {}};
659683
}
660684

685+
auto weak_embedder_isolate = embedder_isolate->GetWeakIsolatePtr();
686+
687+
// Root isolates will be setup by the engine and the service isolate (which is
688+
// also a root isolate) by the utility routines in the VM. However, secondary
689+
// isolates will be run by the VM if they are marked as runnable.
690+
if (!is_root_isolate) {
691+
FXL_DCHECK(embedder_isolate->child_isolate_preparer_);
692+
if (!embedder_isolate->child_isolate_preparer_(embedder_isolate.get())) {
693+
*error = strdup("Could not prepare the child isolate to run.");
694+
FXL_DLOG(ERROR) << *error;
695+
return {nullptr, {}};
696+
}
697+
embedder_isolate->ResetWeakPtrFactory();
698+
}
699+
661700
// The ownership of the embedder object is controlled by the Dart VM. So the
662701
// only reference returned to the caller is weak.
663-
return {isolate, embedder_isolate.release()->GetWeakIsolatePtr()};
702+
embedder_isolate.release();
703+
return {isolate, weak_embedder_isolate};
664704
}
665705

666706
// |Dart_IsolateShutdownCallback|

runtime/dart_isolate.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class DartIsolate : public UIDartState {
3333
Shutdown,
3434
};
3535

36+
using ChildIsolatePreparer = std::function<bool(DartIsolate*)>;
37+
3638
// The root isolate of a Flutter application is special because it gets Window
3739
// bindings. From the VM's perspective, this isolate is not special in any
3840
// way.
@@ -53,7 +55,8 @@ class DartIsolate : public UIDartState {
5355
fml::WeakPtr<GrContext> resource_context,
5456
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
5557
std::string advisory_script_uri,
56-
std::string advisory_script_entrypoint);
58+
std::string advisory_script_entrypoint,
59+
ChildIsolatePreparer child_isolate_preparer);
5760

5861
~DartIsolate() override;
5962

@@ -63,7 +66,8 @@ class DartIsolate : public UIDartState {
6366
bool PrepareForRunningFromPrecompiledCode();
6467

6568
FXL_WARN_UNUSED_RESULT
66-
bool PrepareForRunningFromSnapshot(std::unique_ptr<fml::Mapping> snapshot);
69+
bool PrepareForRunningFromSnapshot(
70+
std::shared_ptr<const fml::Mapping> snapshot);
6771

6872
FXL_WARN_UNUSED_RESULT
6973
bool PrepareForRunningFromSource(const std::string& main_source_file,
@@ -103,6 +107,7 @@ class DartIsolate : public UIDartState {
103107
Phase phase_ = Phase::Unknown;
104108
const fxl::RefPtr<DartSnapshot> isolate_snapshot_;
105109
std::vector<std::unique_ptr<AutoFireClosure>> shutdown_callbacks_;
110+
ChildIsolatePreparer child_isolate_preparer_;
106111
std::unique_ptr<fml::WeakPtrFactory<DartIsolate>> weak_factory_;
107112

108113
FXL_WARN_UNUSED_RESULT

0 commit comments

Comments
 (0)