Flutter Engine
The Flutter Engine
isolate_configuration.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/runtime/isolate_configuration.h"
6
7#include "flutter/fml/make_copyable.h"
8#include "flutter/runtime/dart_vm.h"
9
10namespace flutter {
11
13
15
19 << "Isolate was in incorrect phase to be prepared for running.";
20 return false;
21 }
22
23 return DoPrepareIsolate(isolate);
24}
25
27 public:
29
30 // |IsolateConfiguration|
31 bool DoPrepareIsolate(DartIsolate& isolate) override {
33 }
34
35 // |IsolateConfiguration|
36 bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
37 return snapshot.IsNullSafetyEnabled(nullptr);
38 }
39
40 private:
41 FML_DISALLOW_COPY_AND_ASSIGN(AppSnapshotIsolateConfiguration);
42};
43
45 public:
46 // The kernel mapping may be nullptr if reusing the group's loaded kernel.
48 std::unique_ptr<const fml::Mapping> kernel)
49 : kernel_(std::move(kernel)) {}
50
51 // |IsolateConfiguration|
52 bool DoPrepareIsolate(DartIsolate& isolate) override {
54 return false;
55 }
56 return isolate.PrepareForRunningFromKernel(std::move(kernel_),
57 /*child_isolate=*/false,
58 /*last_piece=*/true);
59 }
60
61 // |IsolateConfiguration|
62 bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
63 return snapshot.IsNullSafetyEnabled(kernel_.get());
64 }
65
66 private:
67 std::unique_ptr<const fml::Mapping> kernel_;
68
69 FML_DISALLOW_COPY_AND_ASSIGN(KernelIsolateConfiguration);
70};
71
73 public:
75 std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
76 kernel_pieces)
77 : kernel_piece_futures_(std::move(kernel_pieces)) {
78 if (kernel_piece_futures_.empty()) {
79 FML_LOG(ERROR) << "Attempted to create kernel list configuration without "
80 "any kernel blobs.";
81 }
82 }
83
84 // |IsolateConfiguration|
85 bool DoPrepareIsolate(DartIsolate& isolate) override {
87 return false;
88 }
89
91
92 if (resolved_kernel_pieces_.empty()) {
93 FML_DLOG(ERROR) << "No kernel pieces provided to prepare this isolate.";
94 return false;
95 }
96
97 for (size_t i = 0; i < resolved_kernel_pieces_.size(); i++) {
98 if (!resolved_kernel_pieces_[i]) {
99 FML_DLOG(ERROR) << "This kernel list isolate configuration was already "
100 "used to prepare an isolate.";
101 return false;
102 }
103 const bool last_piece = i + 1 == resolved_kernel_pieces_.size();
104 if (!isolate.PrepareForRunningFromKernel(
105 std::move(resolved_kernel_pieces_[i]), /*child_isolate=*/false,
106 last_piece)) {
107 return false;
108 }
109 }
110
111 return true;
112 }
113
114 // |IsolateConfiguration|
115 bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
117 const auto kernel = resolved_kernel_pieces_.empty()
118 ? nullptr
119 : resolved_kernel_pieces_.front().get();
120 return snapshot.IsNullSafetyEnabled(kernel);
121 }
122
123 // This must be call as late as possible before accessing any of the kernel
124 // pieces. This will delay blocking on the futures for as long as possible. So
125 // far, only Fuchsia depends on this optimization and only on the non-AOT
126 // configs.
128 if (resolved_kernel_pieces_.size() == kernel_piece_futures_.size()) {
129 return;
130 }
131
132 resolved_kernel_pieces_.clear();
133 for (auto& piece : kernel_piece_futures_) {
134 // The get() call will xfer the unique pointer out and leave an empty
135 // future in the original vector.
136 resolved_kernel_pieces_.emplace_back(piece.get());
137 }
138 }
139
140 private:
141 std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
142 kernel_piece_futures_;
143 std::vector<std::unique_ptr<const fml::Mapping>> resolved_kernel_pieces_;
144
145 FML_DISALLOW_COPY_AND_ASSIGN(KernelListIsolateConfiguration);
146};
147
148static std::vector<std::string> ParseKernelListPaths(
149 std::unique_ptr<fml::Mapping> kernel_list) {
150 FML_DCHECK(kernel_list);
151
152 std::vector<std::string> kernel_pieces_paths;
153
154 const char* kernel_list_str =
155 reinterpret_cast<const char*>(kernel_list->GetMapping());
156 size_t kernel_list_size = kernel_list->GetSize();
157
158 size_t piece_path_start = 0;
159 while (piece_path_start < kernel_list_size) {
160 size_t piece_path_end = piece_path_start;
161 while ((piece_path_end < kernel_list_size) &&
162 (kernel_list_str[piece_path_end] != '\n')) {
163 piece_path_end++;
164 }
165 std::string piece_path(&kernel_list_str[piece_path_start],
166 piece_path_end - piece_path_start);
167 kernel_pieces_paths.emplace_back(std::move(piece_path));
168
169 piece_path_start = piece_path_end + 1;
170 }
171
172 return kernel_pieces_paths;
173}
174
175static std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
176PrepareKernelMappings(const std::vector<std::string>& kernel_pieces_paths,
177 const std::shared_ptr<AssetManager>& asset_manager,
178 const fml::RefPtr<fml::TaskRunner>& io_worker) {
179 FML_DCHECK(asset_manager);
180 std::vector<std::future<std::unique_ptr<const fml::Mapping>>> fetch_futures;
181
182 for (const auto& kernel_pieces_path : kernel_pieces_paths) {
183 std::promise<std::unique_ptr<const fml::Mapping>> fetch_promise;
184 fetch_futures.push_back(fetch_promise.get_future());
185 auto fetch_task =
186 fml::MakeCopyable([asset_manager, kernel_pieces_path,
187 fetch_promise = std::move(fetch_promise)]() mutable {
188 fetch_promise.set_value(
189 asset_manager->GetAsMapping(kernel_pieces_path));
190 });
191 // Fulfill the promise on the worker if one is available or the current
192 // thread if one is not.
193 if (io_worker) {
194 io_worker->PostTask(fetch_task);
195 } else {
196 fetch_task();
197 }
198 }
199
200 return fetch_futures;
201}
202
203std::unique_ptr<IsolateConfiguration> IsolateConfiguration::InferFromSettings(
204 const Settings& settings,
205 const std::shared_ptr<AssetManager>& asset_manager,
206 const fml::RefPtr<fml::TaskRunner>& io_worker,
207 IsolateLaunchType launch_type) {
208 // Running in AOT mode.
210 return CreateForAppSnapshot();
211 }
212
213 if (launch_type == IsolateLaunchType::kExistingGroup) {
214 return CreateForKernel(nullptr);
215 }
216
217 if (settings.application_kernels) {
218 return CreateForKernelList(settings.application_kernels());
219 }
220
221 if (settings.application_kernel_asset.empty() &&
222 settings.application_kernel_list_asset.empty()) {
223 FML_DLOG(ERROR) << "application_kernel_asset or "
224 "application_kernel_list_asset must be set";
225 return nullptr;
226 }
227
228 if (!asset_manager) {
229 FML_DLOG(ERROR) << "No asset manager specified when attempting to create "
230 "isolate configuration.";
231 return nullptr;
232 }
233
234 // Running from kernel snapshot. Requires asset manager.
235 {
236 std::unique_ptr<fml::Mapping> kernel =
237 asset_manager->GetAsMapping(settings.application_kernel_asset);
238 if (kernel) {
239 return CreateForKernel(std::move(kernel));
240 }
241 }
242
243 // Running from kernel divided into several pieces (for sharing). Requires
244 // asset manager and io worker.
245
246 if (!io_worker) {
247 FML_DLOG(ERROR) << "No IO worker specified to load kernel pieces.";
248 return nullptr;
249 }
250
251 {
252 std::unique_ptr<fml::Mapping> kernel_list =
253 asset_manager->GetAsMapping(settings.application_kernel_list_asset);
254 if (!kernel_list) {
255 FML_LOG(ERROR) << "Failed to load: "
256 << settings.application_kernel_list_asset;
257 return nullptr;
258 }
259 auto kernel_pieces_paths = ParseKernelListPaths(std::move(kernel_list));
260 auto kernel_mappings =
261 PrepareKernelMappings(kernel_pieces_paths, asset_manager, io_worker);
262 return CreateForKernelList(std::move(kernel_mappings));
263 }
264
265 return nullptr;
266}
267
268std::unique_ptr<IsolateConfiguration>
270 return std::make_unique<AppSnapshotIsolateConfiguration>();
271}
272
273std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernel(
274 std::unique_ptr<const fml::Mapping> kernel) {
275 return std::make_unique<KernelIsolateConfiguration>(std::move(kernel));
276}
277
278std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
279 std::vector<std::unique_ptr<const fml::Mapping>> kernel_pieces) {
280 std::vector<std::future<std::unique_ptr<const fml::Mapping>>> pieces;
281 for (auto& piece : kernel_pieces) {
282 if (!piece) {
283 FML_DLOG(ERROR) << "Invalid kernel piece.";
284 continue;
285 }
286 std::promise<std::unique_ptr<const fml::Mapping>> promise;
287 pieces.push_back(promise.get_future());
288 promise.set_value(std::move(piece));
289 }
290 return CreateForKernelList(std::move(pieces));
291}
292
293std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
294 std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
295 kernel_pieces) {
296 return std::make_unique<KernelListIsolateConfiguration>(
297 std::move(kernel_pieces));
298}
299
300} // namespace flutter
bool DoPrepareIsolate(DartIsolate &isolate) override
bool IsNullSafetyEnabled(const DartSnapshot &snapshot) override
Represents an instance of a live isolate. An isolate is a separate Dart execution context....
Definition: dart_isolate.h:63
bool PrepareForRunningFromKernel(const std::shared_ptr< const fml::Mapping > &kernel, bool child_isolate, bool last_piece)
Prepare the isolate for running for a a list of kernel files.
Phase GetPhase() const
The current phase of the isolate. The engine represents all dart isolates as being in one of the know...
bool PrepareForRunningFromPrecompiledCode()
Prepare the isolate for running for a precompiled code bundle. The Dart VM must be configured for run...
A read-only Dart heap snapshot, or, read-executable mapping of AOT compiled Dart code.
Definition: dart_snapshot.h:42
bool IsNullSafetyEnabled(const fml::Mapping *application_kernel_mapping) const
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:205
An isolate configuration is a collection of snapshots and asset managers that the engine will use to ...
bool PrepareIsolate(DartIsolate &isolate)
When an isolate is created and sufficiently initialized to move it into the DartIsolate::Phase::Libra...
static std::unique_ptr< IsolateConfiguration > InferFromSettings(const Settings &settings, const std::shared_ptr< AssetManager > &asset_manager=nullptr, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer the isolate configuration from the Settings object. If the VM is configured for AOT...
virtual ~IsolateConfiguration()
Destroys an isolate configuration. This has no threading restrictions and may be collection of config...
IsolateConfiguration()
Create an isolate configuration. This has no threading restrictions.
static std::unique_ptr< IsolateConfiguration > CreateForKernelList(std::vector< std::future< std::unique_ptr< const fml::Mapping > > > kernel_pieces)
Creates a JIT isolate configuration using a list of futures to snapshots defining the ready isolate s...
static std::unique_ptr< IsolateConfiguration > CreateForAppSnapshot()
Creates an AOT isolate configuration using snapshot symbols present in the currently loaded process....
static std::unique_ptr< IsolateConfiguration > CreateForKernel(std::unique_ptr< const fml::Mapping > kernel)
Creates a JIT isolate configuration using the specified snapshot. This is a convenience method for th...
virtual bool DoPrepareIsolate(DartIsolate &isolate)=0
KernelIsolateConfiguration(std::unique_ptr< const fml::Mapping > kernel)
bool DoPrepareIsolate(DartIsolate &isolate) override
bool IsNullSafetyEnabled(const DartSnapshot &snapshot) override
bool DoPrepareIsolate(DartIsolate &isolate) override
KernelListIsolateConfiguration(std::vector< std::future< std::unique_ptr< const fml::Mapping > > > kernel_pieces)
bool IsNullSafetyEnabled(const DartSnapshot &snapshot) override
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
static std::vector< std::string > ParseKernelListPaths(std::unique_ptr< fml::Mapping > kernel_list)
static std::vector< std::future< std::unique_ptr< const fml::Mapping > > > PrepareKernelMappings(const std::vector< std::string > &kernel_pieces_paths, const std::shared_ptr< AssetManager > &asset_manager, const fml::RefPtr< fml::TaskRunner > &io_worker)
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
Definition: ref_ptr.h:256
#define ERROR(message)
Definition: elf_loader.cc:260