• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/shell/common/isolate_configuration.h"
6 
7 #include "flutter/fml/make_copyable.h"
8 #include "flutter/runtime/dart_vm.h"
9 
10 namespace flutter {
11 
12 IsolateConfiguration::IsolateConfiguration() = default;
13 
14 IsolateConfiguration::~IsolateConfiguration() = default;
15 
PrepareIsolate(DartIsolate & isolate)16 bool IsolateConfiguration::PrepareIsolate(DartIsolate& isolate) {
17   if (isolate.GetPhase() != DartIsolate::Phase::LibrariesSetup) {
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 
26 class AppSnapshotIsolateConfiguration final : public IsolateConfiguration {
27  public:
28   AppSnapshotIsolateConfiguration() = default;
29 
30   // |IsolateConfiguration|
DoPrepareIsolate(DartIsolate & isolate)31   bool DoPrepareIsolate(DartIsolate& isolate) override {
32     return isolate.PrepareForRunningFromPrecompiledCode();
33   }
34 
35  private:
36   FML_DISALLOW_COPY_AND_ASSIGN(AppSnapshotIsolateConfiguration);
37 };
38 
39 class KernelIsolateConfiguration : public IsolateConfiguration {
40  public:
KernelIsolateConfiguration(std::unique_ptr<const fml::Mapping> kernel)41   KernelIsolateConfiguration(std::unique_ptr<const fml::Mapping> kernel)
42       : kernel_(std::move(kernel)) {}
43 
44   // |IsolateConfiguration|
DoPrepareIsolate(DartIsolate & isolate)45   bool DoPrepareIsolate(DartIsolate& isolate) override {
46     if (DartVM::IsRunningPrecompiledCode()) {
47       return false;
48     }
49     return isolate.PrepareForRunningFromKernel(std::move(kernel_));
50   }
51 
52  private:
53   std::unique_ptr<const fml::Mapping> kernel_;
54 
55   FML_DISALLOW_COPY_AND_ASSIGN(KernelIsolateConfiguration);
56 };
57 
58 class KernelListIsolateConfiguration final : public IsolateConfiguration {
59  public:
KernelListIsolateConfiguration(std::vector<std::future<std::unique_ptr<const fml::Mapping>>> kernel_pieces)60   KernelListIsolateConfiguration(
61       std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
62           kernel_pieces)
63       : kernel_pieces_(std::move(kernel_pieces)) {}
64 
65   // |IsolateConfiguration|
DoPrepareIsolate(DartIsolate & isolate)66   bool DoPrepareIsolate(DartIsolate& isolate) override {
67     if (DartVM::IsRunningPrecompiledCode()) {
68       return false;
69     }
70 
71     for (size_t i = 0; i < kernel_pieces_.size(); i++) {
72       bool last_piece = i + 1 == kernel_pieces_.size();
73 
74       if (!isolate.PrepareForRunningFromKernel(kernel_pieces_[i].get(),
75                                                last_piece)) {
76         return false;
77       }
78     }
79 
80     return true;
81   }
82 
83  private:
84   std::vector<std::future<std::unique_ptr<const fml::Mapping>>> kernel_pieces_;
85 
86   FML_DISALLOW_COPY_AND_ASSIGN(KernelListIsolateConfiguration);
87 };
88 
ParseKernelListPaths(std::unique_ptr<fml::Mapping> kernel_list)89 static std::vector<std::string> ParseKernelListPaths(
90     std::unique_ptr<fml::Mapping> kernel_list) {
91   FML_DCHECK(kernel_list);
92 
93   std::vector<std::string> kernel_pieces_paths;
94 
95   const char* kernel_list_str =
96       reinterpret_cast<const char*>(kernel_list->GetMapping());
97   size_t kernel_list_size = kernel_list->GetSize();
98 
99   size_t piece_path_start = 0;
100   while (piece_path_start < kernel_list_size) {
101     size_t piece_path_end = piece_path_start;
102     while ((piece_path_end < kernel_list_size) &&
103            (kernel_list_str[piece_path_end] != '\n')) {
104       piece_path_end++;
105     }
106     std::string piece_path(&kernel_list_str[piece_path_start],
107                            piece_path_end - piece_path_start);
108     kernel_pieces_paths.emplace_back(std::move(piece_path));
109 
110     piece_path_start = piece_path_end + 1;
111   }
112 
113   return kernel_pieces_paths;
114 }
115 
116 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)117 PrepareKernelMappings(std::vector<std::string> kernel_pieces_paths,
118                       std::shared_ptr<AssetManager> asset_manager,
119                       fml::RefPtr<fml::TaskRunner> io_worker) {
120   FML_DCHECK(asset_manager);
121   std::vector<std::future<std::unique_ptr<const fml::Mapping>>> fetch_futures;
122 
123   for (const auto& kernel_pieces_path : kernel_pieces_paths) {
124     std::promise<std::unique_ptr<const fml::Mapping>> fetch_promise;
125     fetch_futures.push_back(fetch_promise.get_future());
126     auto fetch_task =
127         fml::MakeCopyable([asset_manager, kernel_pieces_path,
128                            fetch_promise = std::move(fetch_promise)]() mutable {
129           fetch_promise.set_value(
130               asset_manager->GetAsMapping(kernel_pieces_path));
131         });
132     // Fulfill the promise on the worker if one is available or the current
133     // thread if one is not.
134     if (io_worker) {
135       io_worker->PostTask(fetch_task);
136     } else {
137       fetch_task();
138     }
139   }
140 
141   return fetch_futures;
142 }
143 
InferFromSettings(const Settings & settings,std::shared_ptr<AssetManager> asset_manager,fml::RefPtr<fml::TaskRunner> io_worker)144 std::unique_ptr<IsolateConfiguration> IsolateConfiguration::InferFromSettings(
145     const Settings& settings,
146     std::shared_ptr<AssetManager> asset_manager,
147     fml::RefPtr<fml::TaskRunner> io_worker) {
148   // Running in AOT mode.
149   if (DartVM::IsRunningPrecompiledCode()) {
150     return CreateForAppSnapshot();
151   }
152 
153   if (!asset_manager) {
154     return nullptr;
155   }
156 
157   if (settings.application_kernels) {
158     return CreateForKernelList(settings.application_kernels());
159   }
160 
161   if (settings.application_kernel_asset.empty() &&
162       settings.application_kernel_list_asset.empty()) {
163     FML_DLOG(ERROR) << "application_kernel_asset or "
164                        "application_kernel_list_asset must be set";
165     return nullptr;
166   }
167 
168   // Running from kernel snapshot.
169   {
170     std::unique_ptr<fml::Mapping> kernel =
171         asset_manager->GetAsMapping(settings.application_kernel_asset);
172     if (kernel) {
173       return CreateForKernel(std::move(kernel));
174     }
175   }
176 
177   // Running from kernel divided into several pieces (for sharing).
178   {
179     std::unique_ptr<fml::Mapping> kernel_list =
180         asset_manager->GetAsMapping(settings.application_kernel_list_asset);
181     if (!kernel_list) {
182       FML_LOG(ERROR) << "Failed to load: " << settings.application_kernel_asset;
183       return nullptr;
184     }
185     auto kernel_pieces_paths = ParseKernelListPaths(std::move(kernel_list));
186     auto kernel_mappings = PrepareKernelMappings(std::move(kernel_pieces_paths),
187                                                  asset_manager, io_worker);
188     return CreateForKernelList(std::move(kernel_mappings));
189   }
190 
191   return nullptr;
192 }
193 
194 std::unique_ptr<IsolateConfiguration>
CreateForAppSnapshot()195 IsolateConfiguration::CreateForAppSnapshot() {
196   return std::make_unique<AppSnapshotIsolateConfiguration>();
197 }
198 
CreateForKernel(std::unique_ptr<const fml::Mapping> kernel)199 std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernel(
200     std::unique_ptr<const fml::Mapping> kernel) {
201   return std::make_unique<KernelIsolateConfiguration>(std::move(kernel));
202 }
203 
CreateForKernelList(std::vector<std::unique_ptr<const fml::Mapping>> kernel_pieces)204 std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
205     std::vector<std::unique_ptr<const fml::Mapping>> kernel_pieces) {
206   std::vector<std::future<std::unique_ptr<const fml::Mapping>>> pieces;
207   for (auto& piece : kernel_pieces) {
208     std::promise<std::unique_ptr<const fml::Mapping>> promise;
209     pieces.push_back(promise.get_future());
210     promise.set_value(std::move(piece));
211   }
212   return CreateForKernelList(std::move(pieces));
213 }
214 
CreateForKernelList(std::vector<std::future<std::unique_ptr<const fml::Mapping>>> kernel_pieces)215 std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
216     std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
217         kernel_pieces) {
218   return std::make_unique<KernelListIsolateConfiguration>(
219       std::move(kernel_pieces));
220 }
221 
222 }  // namespace flutter
223