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