• 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 "service_isolate.h"
6 
7 #include "runtime/dart/utils/inlines.h"
8 #include "third_party/dart/runtime/include/bin/dart_io_api.h"
9 #include "third_party/tonic/converter/dart_converter.h"
10 #include "third_party/tonic/dart_library_natives.h"
11 #include "third_party/tonic/dart_microtask_queue.h"
12 #include "third_party/tonic/dart_state.h"
13 #include "third_party/tonic/typed_data/typed_list.h"
14 
15 #include "builtin_libraries.h"
16 #include "dart_component_controller.h"
17 #include "logging.h"
18 
19 namespace dart_runner {
20 namespace {
21 
22 MappedResource mapped_isolate_snapshot_data;
23 MappedResource mapped_isolate_snapshot_instructions;
24 MappedResource mapped_shared_snapshot_data;
25 MappedResource mapped_shared_snapshot_instructions;
26 tonic::DartLibraryNatives* service_natives = nullptr;
27 
GetNativeFunction(Dart_Handle name,int argument_count,bool * auto_setup_scope)28 Dart_NativeFunction GetNativeFunction(Dart_Handle name,
29                                       int argument_count,
30                                       bool* auto_setup_scope) {
31   dart_utils::Check(service_natives, LOG_TAG);
32   return service_natives->GetNativeFunction(name, argument_count,
33                                             auto_setup_scope);
34 }
35 
GetSymbol(Dart_NativeFunction native_function)36 const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
37   dart_utils::Check(service_natives, LOG_TAG);
38   return service_natives->GetSymbol(native_function);
39 }
40 
41 #define SHUTDOWN_ON_ERROR(handle)           \
42   if (Dart_IsError(handle)) {               \
43     *error = strdup(Dart_GetError(handle)); \
44     FX_LOG(ERROR, LOG_TAG, *error);         \
45     Dart_ExitScope();                       \
46     Dart_ShutdownIsolate();                 \
47     return nullptr;                         \
48   }
49 
NotifyServerState(Dart_NativeArguments args)50 void NotifyServerState(Dart_NativeArguments args) {
51   // NOP.
52 }
53 
Shutdown(Dart_NativeArguments args)54 void Shutdown(Dart_NativeArguments args) {
55   // NOP.
56 }
57 
EmbedderInformationCallback(Dart_EmbedderInformation * info)58 void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
59   info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
60   info->name = "dart_runner";
61   info->current_rss = -1;
62   info->max_rss = -1;
63 
64   zx_info_task_stats_t task_stats;
65   zx_handle_t process = zx_process_self();
66   zx_status_t status = zx_object_get_info(
67       process, ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL);
68   if (status == ZX_OK) {
69     info->current_rss =
70         task_stats.mem_private_bytes + task_stats.mem_shared_bytes;
71   }
72 }
73 
74 }  // namespace
75 
CreateServiceIsolate(const char * uri,Dart_IsolateFlags * flags,char ** error)76 Dart_Isolate CreateServiceIsolate(const char* uri,
77                                   Dart_IsolateFlags* flags,
78                                   char** error) {
79   Dart_SetEmbedderInformationCallback(EmbedderInformationCallback);
80 
81 #if defined(AOT_RUNTIME)
82   // The VM service was compiled as a separate app.
83   const char* snapshot_data_path =
84       "pkg/data/vmservice_isolate_snapshot_data.bin";
85   const char* snapshot_instructions_path =
86       "pkg/data/vmservice_isolate_snapshot_instructions.bin";
87 #else
88   // The VM service is embedded in the core snapshot.
89   const char* snapshot_data_path = "pkg/data/isolate_core_snapshot_data.bin";
90   const char* snapshot_instructions_path =
91       "pkg/data/isolate_core_snapshot_instructions.bin";
92 #endif
93 
94   if (!MappedResource::LoadFromNamespace(nullptr, snapshot_data_path,
95                                          mapped_isolate_snapshot_data)) {
96     *error = strdup("Failed to load snapshot for service isolate");
97     FX_LOG(ERROR, LOG_TAG, *error);
98     return nullptr;
99   }
100   if (!MappedResource::LoadFromNamespace(nullptr, snapshot_instructions_path,
101                                          mapped_isolate_snapshot_instructions,
102                                          true /* executable */)) {
103     *error = strdup("Failed to load snapshot for service isolate");
104     FX_LOG(ERROR, LOG_TAG, *error);
105     return nullptr;
106   }
107 
108 #if defined(AOT_RUNTIME)
109   if (!MappedResource::LoadFromNamespace(
110           nullptr, "pkg/data/vmservice_shared_snapshot_data.bin",
111           mapped_shared_snapshot_data)) {
112     *error = strdup("Failed to load snapshot for service isolate");
113     FX_LOG(ERROR, LOG_TAG, *error);
114     return nullptr;
115   }
116   if (!MappedResource::LoadFromNamespace(
117           nullptr, "pkg/data/vmservice_shared_snapshot_instructions.bin",
118           mapped_shared_snapshot_instructions, true /* executable */)) {
119     *error = strdup("Failed to load snapshot for service isolate");
120     FX_LOG(ERROR, LOG_TAG, *error);
121     return nullptr;
122   }
123 #endif
124 
125   auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
126   Dart_Isolate isolate = Dart_CreateIsolateGroup(
127       uri, DART_VM_SERVICE_ISOLATE_NAME, mapped_isolate_snapshot_data.address(),
128       mapped_isolate_snapshot_instructions.address(),
129       mapped_shared_snapshot_data.address(),
130       mapped_shared_snapshot_instructions.address(), nullptr /* flags */,
131       state /* isolate_group_data */, state /* isolate_data */, error);
132   if (!isolate) {
133     FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
134     return nullptr;
135   }
136 
137   state->get()->SetIsolate(isolate);
138 
139   // Setup native entries.
140   service_natives = new tonic::DartLibraryNatives();
141   service_natives->Register({
142       {"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
143       {"VMServiceIO_Shutdown", Shutdown, 0, true},
144   });
145 
146   Dart_EnterScope();
147 
148   Dart_Handle library =
149       Dart_LookupLibrary(Dart_NewStringFromCString("dart:vmservice_io"));
150   SHUTDOWN_ON_ERROR(library);
151   Dart_Handle result = Dart_SetRootLibrary(library);
152   SHUTDOWN_ON_ERROR(result);
153   result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
154   SHUTDOWN_ON_ERROR(result);
155 
156   // _ip = '127.0.0.1'
157   result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
158                          Dart_NewStringFromCString("127.0.0.1"));
159   SHUTDOWN_ON_ERROR(result);
160 
161   // _port = 0
162   result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
163                          Dart_NewInteger(0));
164   SHUTDOWN_ON_ERROR(result);
165 
166   // _autoStart = true
167   result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
168                          Dart_NewBoolean(true));
169   SHUTDOWN_ON_ERROR(result);
170 
171   // _originCheckDisabled = false
172   result =
173       Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
174                     Dart_NewBoolean(false));
175   SHUTDOWN_ON_ERROR(result);
176 
177   // _authCodesDisabled = false
178   result =
179       Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
180                     Dart_NewBoolean(false));
181   SHUTDOWN_ON_ERROR(result);
182 
183   InitBuiltinLibrariesForIsolate(std::string(uri), nullptr, fileno(stdout),
184                                  fileno(stderr), nullptr, zx::channel(), true);
185 
186   // Make runnable.
187   Dart_ExitScope();
188   Dart_ExitIsolate();
189   *error = Dart_IsolateMakeRunnable(isolate);
190   if (*error != nullptr) {
191     FX_LOG(ERROR, LOG_TAG, *error);
192     Dart_EnterIsolate(isolate);
193     Dart_ShutdownIsolate();
194     return nullptr;
195   }
196   return isolate;
197 }  // namespace dart_runner
198 
GetVMServiceAssetsArchiveCallback()199 Dart_Handle GetVMServiceAssetsArchiveCallback() {
200   MappedResource observatory_tar;
201   if (!MappedResource::LoadFromNamespace(nullptr, "pkg/data/observatory.tar",
202                                          observatory_tar)) {
203     FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets");
204     return nullptr;
205   }
206   // TODO(rmacnak): Should we avoid copying the tar? Or does the service library
207   // not hold onto it anyway?
208   return tonic::DartConverter<tonic::Uint8List>::ToDart(
209       reinterpret_cast<const uint8_t*>(observatory_tar.address()),
210       observatory_tar.size());
211 }
212 
213 }  // namespace dart_runner
214