Flutter Engine
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/syslog/global.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/trace_event.h"
21 #include "logging.h"
24 #include "service_isolate.h"
25 #include "third_party/dart/runtime/include/bin/dart_io_api.h"
28 
29 #if defined(AOT_RUNTIME)
30 extern "C" uint8_t _kDartVmSnapshotData[];
31 extern "C" uint8_t _kDartVmSnapshotInstructions[];
32 #endif
33 
34 namespace dart_runner {
35 namespace {
36 
37 const char* kDartVMArgs[] = {
38  // clang-format off
39  "--no_causal_async_stacks",
40  "--lazy_async_stacks",
41 
42  "--systrace_timeline",
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  // clang-format on
58 };
59 
60 Dart_Isolate IsolateGroupCreateCallback(const char* uri,
61  const char* name,
62  const char* package_root,
63  const char* package_config,
64  Dart_IsolateFlags* flags,
65  void* callback_data,
66  char** error) {
67  if (std::string(uri) == DART_VM_SERVICE_ISOLATE_NAME) {
68 #if defined(DART_PRODUCT)
69  *error = strdup("The service isolate is not implemented in product mode");
70  return NULL;
71 #else
72  return CreateServiceIsolate(uri, flags, error);
73 #endif
74  }
75 
76  *error = strdup("Isolate spawning is not implemented in dart_runner");
77  return NULL;
78 }
79 
80 void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
81  // The service isolate (and maybe later the kernel isolate) doesn't have an
82  // async loop.
83  auto dispatcher = async_get_default_dispatcher();
84  auto loop = async_loop_from_dispatcher(dispatcher);
85  if (loop) {
87  async_loop_quit(loop);
88  }
89 }
90 
91 void IsolateGroupCleanupCallback(void* isolate_group_data) {
92  delete static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
93 }
94 
95 void RunApplication(
96  DartRunner* runner,
97  fuchsia::sys::Package package,
98  fuchsia::sys::StartupInfo startup_info,
99  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
100  ::fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
101  int64_t start = Dart_TimelineGetMicros();
102  DartComponentController app(std::move(package), std::move(startup_info),
103  runner_incoming_services, std::move(controller));
104  bool success = app.Setup();
105  int64_t end = Dart_TimelineGetMicros();
106  Dart_TimelineEvent("DartComponentController::Setup", start, end,
107  Dart_Timeline_Event_Duration, 0, NULL, NULL);
108  if (success) {
109  app.Run();
110  }
111 
112  if (Dart_CurrentIsolate()) {
113  Dart_ShutdownIsolate();
114  }
115 }
116 
117 bool EntropySource(uint8_t* buffer, intptr_t count) {
118  zx_cprng_draw(buffer, count);
119  return true;
120 }
121 
122 } // namespace
123 
124 DartRunner::DartRunner(sys::ComponentContext* context) : context_(context) {
125  context_->outgoing()->AddPublicService<fuchsia::sys::Runner>(
126  [this](fidl::InterfaceRequest<fuchsia::sys::Runner> request) {
127  bindings_.AddBinding(this, std::move(request));
128  });
129 
130 #if !defined(DART_PRODUCT)
131  // The VM service isolate uses the process-wide namespace. It writes the
132  // vm service protocol port under /tmp. The VMServiceObject exposes that
133  // port number to The Hub.
134  context_->outgoing()->debug_dir()->AddEntry(
136  std::make_unique<dart_utils::VMServiceObject>());
137 
138 #endif // !defined(DART_PRODUCT)
139 
140  dart::bin::BootstrapDartIo();
141 
142  char* error =
143  Dart_SetVMFlags(dart_utils::ArraySize(kDartVMArgs), kDartVMArgs);
144  if (error) {
145  FX_LOGF(FATAL, LOG_TAG, "Dart_SetVMFlags failed: %s", error);
146  }
147 
148  Dart_InitializeParams params = {};
149  params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
150 #if defined(AOT_RUNTIME)
151  params.vm_snapshot_data = ::_kDartVmSnapshotData;
152  params.vm_snapshot_instructions = ::_kDartVmSnapshotInstructions;
153 #else
155  nullptr, "/pkg/data/vm_snapshot_data.bin", vm_snapshot_data_)) {
156  FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot data");
157  }
159  nullptr, "/pkg/data/vm_snapshot_instructions.bin",
160  vm_snapshot_instructions_, true /* executable */)) {
161  FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot instructions");
162  }
163  params.vm_snapshot_data = vm_snapshot_data_.address();
164  params.vm_snapshot_instructions = vm_snapshot_instructions_.address();
165 #endif
166  params.create_group = IsolateGroupCreateCallback;
167  params.shutdown_isolate = IsolateShutdownCallback;
168  params.cleanup_group = IsolateGroupCleanupCallback;
169  params.entropy_source = EntropySource;
170 #if !defined(DART_PRODUCT)
171  params.get_service_assets = GetVMServiceAssetsArchiveCallback;
172 #endif
173  error = Dart_Initialize(&params);
174  if (error)
175  FX_LOGF(FATAL, LOG_TAG, "Dart_Initialize failed: %s", error);
176 }
177 
179  char* error = Dart_Cleanup();
180  if (error)
181  FX_LOGF(FATAL, LOG_TAG, "Dart_Cleanup failed: %s", error);
182 }
183 
184 void DartRunner::StartComponent(
185  fuchsia::sys::Package package,
186  fuchsia::sys::StartupInfo startup_info,
187  ::fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
188  // TRACE_DURATION currently requires that the string data does not change
189  // in the traced scope. Since |package| gets moved in the construction of
190  // |thread| below, we cannot ensure that |package.resolved_url| does not
191  // move or change, so we make a copy to pass to TRACE_DURATION.
192  // TODO(PT-169): Remove this copy when TRACE_DURATION reads string arguments
193  // eagerly.
194  std::string url_copy = package.resolved_url;
195  TRACE_EVENT1("dart", "StartComponent", "url", url_copy.c_str());
196  std::thread thread(RunApplication, this, std::move(package),
197  std::move(startup_info), context_->svc(),
198  std::move(controller));
199  thread.detach();
200 }
201 
202 } // namespace dart_runner
static DartMicrotaskQueue * GetForCurrentThread()
size_t ArraySize(T(&array)[SIZE])
Definition: inlines.h:26
FlMethodResponse GError ** error
Dart_Handle GetVMServiceAssetsArchiveCallback()
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
Dart_Isolate CreateServiceIsolate(const char *uri, Dart_IsolateFlags *flags, char **error)
const uint8_t * address() const
#define LOG_TAG
Definition: logging.h:11
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:79
const char * name
Definition: fuchsia.cc:50
char * strdup(const char *str1)
static constexpr const char * kPortDirName
DartRunner(sys::ComponentContext *context)
Definition: dart_runner.cc:124
DEF_SWITCHES_START snapshot asset Path to the directory containing the four files specified by VmSnapshotInstructions and IsolateSnapshotInstructions vm snapshot The VM instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present isolate snapshot The isolate instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present icu symbol Prefix for the symbols representing ICU data linked into the Flutter library dart flags
Definition: switches.h:66