Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dart_runner.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 "dart_runner.h"
6
7#include <lib/async-loop/loop.h>
8#include <lib/async/default.h>
9#include <lib/vfs/cpp/pseudo_dir.h>
10#include <sys/stat.h>
11#include <zircon/status.h>
12#include <zircon/syscalls.h>
13
14#include <cerrno>
15#include <memory>
16#include <thread>
17#include <utility>
18
20#include "flutter/fml/command_line.h"
21#include "flutter/fml/logging.h"
22#include "flutter/fml/trace_event.h"
25#include "service_isolate.h"
26#include "third_party/dart/runtime/include/bin/dart_io_api.h"
29
30#if defined(AOT_RUNTIME)
31extern "C" uint8_t _kDartVmSnapshotData[];
32extern "C" uint8_t _kDartVmSnapshotInstructions[];
33#endif
34
35namespace dart_runner {
36
37namespace {
38
39const char* kDartVMArgs[] = {
40 // clang-format off
41
42 "--timeline_recorder=systrace",
43 "--timeline_streams=Compiler,Dart,Debugger,Embedder,GC,Isolate,VM",
44
45#if defined(AOT_RUNTIME)
46 "--precompilation",
47#else
48 "--enable_mirrors=false",
49#endif
50
51 // No asserts in debug or release product.
52 // No asserts in release with flutter_profile=true (non-product)
53 // Yes asserts in non-product debug.
54#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
55 "--enable_asserts",
56#endif
57};
58
59Dart_Isolate IsolateGroupCreateCallback(const char* uri,
60 const char* name,
61 const char* package_root,
62 const char* package_config,
64 void* callback_data,
65 char** error) {
66 if (std::string(uri) == DART_VM_SERVICE_ISOLATE_NAME) {
67#if defined(DART_PRODUCT)
68 *error = strdup("The service isolate is not implemented in product mode");
69 return NULL;
70#else
71 return CreateServiceIsolate(uri, flags, error);
72#endif
73 }
74
75 *error = strdup("Isolate spawning is not implemented in dart_runner");
76 return NULL;
77}
78
79void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
80 // The service isolate (and maybe later the kernel isolate) doesn't have an
81 // async loop.
82 auto dispatcher = async_get_default_dispatcher();
83 auto loop = async_loop_from_dispatcher(dispatcher);
84 if (loop) {
87 if (queue) {
88 queue->Destroy();
89 }
90
91 async_loop_quit(loop);
92 }
93
94 auto state =
95 static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
96 state->get()->SetIsShuttingDown();
97}
98
99void IsolateGroupCleanupCallback(void* isolate_group_data) {
100 delete static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
101}
102
103// Runs the application for a Dart component.
104void RunApplication(
105 DartRunner* runner,
106 fuchsia::component::runner::ComponentStartInfo start_info,
107 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
108 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
109 controller) {
110 const int64_t start = Dart_TimelineGetMicros();
111
112 DartComponentController app(std::move(start_info), runner_incoming_services,
113 std::move(controller));
114 const bool success = app.SetUp();
115
116 const int64_t end = Dart_TimelineGetMicros();
118 "DartComponentController::SetUp", start, end, 0, nullptr,
119 Dart_Timeline_Event_Duration, 0, NULL, NULL);
120 if (success) {
121 app.Run();
122 }
123
124 if (Dart_CurrentIsolate()) {
126 }
127}
128
129void RunTestApplication(
130 DartRunner* runner,
131 fuchsia::component::runner::ComponentStartInfo start_info,
132 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
133 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
134 controller,
135 fit::function<void(std::shared_ptr<DartTestComponentController>)>
136 component_created_callback,
137 fit::function<void(DartTestComponentController*)> done_callback) {
138 const int64_t start = Dart_TimelineGetMicros();
139
140 auto test_component = std::make_shared<DartTestComponentController>(
141 std::move(start_info), runner_incoming_services, std::move(controller),
142 std::move(done_callback));
143
144 component_created_callback(test_component);
145
146 // Start up the dart isolate and serve the suite protocol.
147 test_component->SetUp();
148
149 const int64_t end = Dart_TimelineGetMicros();
151 "DartTestComponentController::SetUp", start, end, 0, nullptr,
152 Dart_Timeline_Event_Duration, 0, NULL, NULL);
153}
154
155bool EntropySource(uint8_t* buffer, intptr_t count) {
156 zx_cprng_draw(buffer, count);
157 return true;
158}
159
160} // namespace
161
162// "args" are how the component specifies arguments to the runner.
163constexpr char kArgsKey[] = "args";
164
165/// Parses the |args| field from the "program" field to determine
166/// if a test component is being executed.
167bool IsTestProgram(const fuchsia::data::Dictionary& program_metadata) {
168 for (const auto& entry : program_metadata.entries()) {
169 if (entry.key.compare(kArgsKey) != 0 || entry.value == nullptr) {
170 continue;
171 }
172 auto args = entry.value->str_vec();
173
174 // fml::CommandLine expects the first argument to be the name of the
175 // program, so we prepend a dummy argument so we can use fml::CommandLine to
176 // parse the arguments for us.
177 std::vector<std::string> command_line_args = {""};
178 command_line_args.insert(command_line_args.end(), args.begin(), args.end());
180 command_line_args.begin(), command_line_args.end());
181
182 std::string is_test_str;
183 return parsed_args.GetOptionValue("is_test", &is_test_str) &&
184 is_test_str == "true";
185 }
186 return false;
187}
188
189DartRunner::DartRunner(sys::ComponentContext* context) : context_(context) {
190 context_->outgoing()
191 ->AddPublicService<fuchsia::component::runner::ComponentRunner>(
192 [this](fidl::InterfaceRequest<
193 fuchsia::component::runner::ComponentRunner> request) {
194 component_runner_bindings_.AddBinding(this, std::move(request));
195 });
196
197#if !defined(DART_PRODUCT)
198 // The VM service isolate uses the process-wide namespace. It writes the
199 // vm service protocol port under /tmp. The VMServiceObject exposes that
200 // port number to The Hub.
201 context_->outgoing()->debug_dir()->AddEntry(
203 std::make_unique<dart_utils::VMServiceObject>());
204
205#endif // !defined(DART_PRODUCT)
206
208
209 char* error =
210 Dart_SetVMFlags(dart_utils::ArraySize(kDartVMArgs), kDartVMArgs);
211 if (error) {
212 FML_LOG(FATAL) << "Dart_SetVMFlags failed: " << error;
213 }
214
217#if defined(AOT_RUNTIME)
218 params.vm_snapshot_data = ::_kDartVmSnapshotData;
219 params.vm_snapshot_instructions = ::_kDartVmSnapshotInstructions;
220#else
222 nullptr, "/pkg/data/vm_snapshot_data.bin", vm_snapshot_data_)) {
223 FML_LOG(FATAL) << "Failed to load vm snapshot data";
224 }
225 params.vm_snapshot_data = vm_snapshot_data_.address();
226#endif
227 params.create_group = IsolateGroupCreateCallback;
228 params.shutdown_isolate = IsolateShutdownCallback;
229 params.cleanup_group = IsolateGroupCleanupCallback;
230 params.entropy_source = EntropySource;
231#if !defined(DART_PRODUCT)
232 params.get_service_assets = GetVMServiceAssetsArchiveCallback;
233#endif
235 if (error)
236 FML_LOG(FATAL) << "Dart_Initialize failed: " << error;
237}
238
240 char* error = Dart_Cleanup();
241 if (error)
242 FML_LOG(FATAL) << "Dart_Cleanup failed: " << error;
243}
244
246 fuchsia::component::runner::ComponentStartInfo start_info,
247 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
248 controller) {
249 // Parse the program field of the component's cml and check if it is a test
250 // component. If so, serve the |fuchsia.test.Suite| protocol from the
251 // component's outgoing directory, via DartTestComponentController.
252 if (IsTestProgram(start_info.program())) {
253 std::string url_copy = start_info.resolved_url();
254 TRACE_EVENT1("dart", "Start", "url", url_copy.c_str());
255 std::thread thread(
256 RunTestApplication, this, std::move(start_info), context_->svc(),
257 std::move(controller),
258 // component_created_callback
259 [this](std::shared_ptr<DartTestComponentController> ptr) {
260 test_components_.emplace(ptr.get(), std::move(ptr));
261 },
262 // done_callback
263 [this](DartTestComponentController* ptr) {
264 auto it = test_components_.find(ptr);
265 if (it != test_components_.end()) {
266 test_components_.erase(it);
267 }
268 });
269 thread.detach();
270 } else {
271 std::string url_copy = start_info.resolved_url();
272 TRACE_EVENT1("dart", "Start", "url", url_copy.c_str());
273 std::thread thread(RunApplication, this, std::move(start_info),
274 context_->svc(), std::move(controller));
275 thread.detach();
276 }
277}
278
279} // namespace dart_runner
int count
void Start(fuchsia::component::runner::ComponentStartInfo start_info, fidl::InterfaceRequest< fuchsia::component::runner::ComponentController > controller) override
DartRunner(sys::ComponentContext *context)
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
const uint8_t * address() const
static constexpr const char * kPortDirName
bool GetOptionValue(std::string_view name, std::string *value) const
static DartMicrotaskQueue * GetForCurrentThread()
#define DART_INITIALIZE_PARAMS_CURRENT_VERSION
Definition dart_api.h:839
DART_EXPORT void Dart_ShutdownIsolate(void)
struct _Dart_Isolate * Dart_Isolate
Definition dart_api.h:88
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_Initialize(Dart_InitializeParams *params)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_Cleanup(void)
#define DART_VM_SERVICE_ISOLATE_NAME
Definition dart_api.h:3831
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_SetVMFlags(int argc, const char **argv)
DART_EXPORT int64_t Dart_TimelineGetMicros()
@ Dart_Timeline_Event_Duration
DART_EXPORT void Dart_RecordTimelineEvent(const char *label, int64_t timestamp0, int64_t timestamp1_or_id, intptr_t flow_id_count, const int64_t *flow_ids, Dart_Timeline_Event_Type type, intptr_t argument_count, const char **argument_names, const char **argument_values)
const EmbeddedViewParams * params
VkQueue queue
Definition main.cc:55
#define FATAL(error)
AtkStateType state
FlutterSemanticsFlag flags
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
Definition logging.h:82
const char * name
Definition fuchsia.cc:50
void BootstrapDartIo()
constexpr char kArgsKey[]
bool IsTestProgram(const fuchsia::data::Dictionary &program_metadata)
Dart_Handle GetVMServiceAssetsArchiveCallback()
Dart_Isolate CreateServiceIsolate(const char *uri, Dart_IsolateFlags *flags_unused, char **error)
size_t ArraySize(T(&array)[SIZE])
Definition inlines.h:11
char * strdup(const char *str1)
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)