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