blob: 34557307dff4f268caaa51f0d02a5007c40399df [file] [log] [blame]
ager@google.com607eea12012-01-10 16:50:14 +00001// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
dgrove@google.com4c0f5592011-10-05 05:20:07 +00002// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
Zachary Anderson6cd8a792017-07-13 08:08:33 -07005#include <stdio.h>
dgrove@google.com4c0f5592011-10-05 05:20:07 +00006#include <stdlib.h>
7#include <string.h>
dgrove@google.com4c0f5592011-10-05 05:20:07 +00008
9#include "include/dart_api.h"
John McCutchanbcf6eb72015-06-17 14:56:55 -070010#include "include/dart_tools_api.h"
dgrove@google.com4c0f5592011-10-05 05:20:07 +000011
12#include "bin/builtin.h"
asiva@google.com0ce82982011-11-18 18:24:04 +000013#include "bin/dartutils.h"
Siva Annamalai286dd512017-05-25 15:40:36 -070014#include "bin/dfe.h"
iposva@google.com67b02b42012-03-07 22:57:57 +000015#include "bin/directory.h"
Todd Turnidgeb243fa52015-11-19 09:24:23 -080016#include "bin/embedded_dart_io.h"
Ryan Macnak6500f6e2017-02-13 11:17:31 -080017#include "bin/error_exit.h"
sgjesse@google.coma6071e02012-01-09 07:38:30 +000018#include "bin/eventhandler.h"
whesse@google.com0e400022012-02-23 13:25:11 +000019#include "bin/extensions.h"
dgrove@google.com4c0f5592011-10-05 05:20:07 +000020#include "bin/file.h"
ager@google.comf791a122012-06-29 14:40:17 +000021#include "bin/isolate_data.h"
John McCutchan6fd8fd72016-06-06 14:15:01 -070022#include "bin/loader.h"
gram@google.com36019442012-11-19 17:38:15 +000023#include "bin/log.h"
sgjesse@google.comd7c8c1f2011-11-23 14:49:18 +000024#include "bin/platform.h"
ager@google.comed3338d2012-02-01 18:16:45 +000025#include "bin/process.h"
Ryan Macnak6500f6e2017-02-13 11:17:31 -080026#include "bin/snapshot_utils.h"
iposva@google.come57e60c2014-08-14 05:00:37 +000027#include "bin/thread.h"
Ivan Posva6249c2b2015-12-03 17:46:02 -080028#include "bin/utils.h"
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +000029#include "bin/vmservice_impl.h"
ager@google.comc4c92c42012-01-06 11:28:21 +000030#include "platform/globals.h"
P.Y. Laligand8f035202017-03-27 06:44:21 -070031#include "platform/growable_array.h"
sgjesse@google.com36a67fa2013-10-31 05:46:57 +000032#include "platform/hashmap.h"
Ivan Posva6249c2b2015-12-03 17:46:02 -080033#include "platform/text_buffer.h"
Zachary Anderson7308e582016-03-29 11:22:03 -070034#if !defined(DART_PRECOMPILER)
Ryan Macnak7dfe62f2017-08-11 12:18:16 -070035#include "bin/gzip.h"
Zachary Anderson7308e582016-03-29 11:22:03 -070036#endif
ager@google.comc4c92c42012-01-06 11:28:21 +000037
Kevin Millikin385f8fb2017-04-25 20:04:20 +020038#include "vm/kernel.h"
39
Ryan Macnak14ec8fa2017-05-24 14:38:09 -070040extern "C" {
41extern const uint8_t kDartVmSnapshotData[];
42extern const uint8_t kDartVmSnapshotInstructions[];
43extern const uint8_t kDartCoreIsolateSnapshotData[];
44extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
45}
46
smok@google.comebbc2022013-04-25 14:22:30 +000047namespace dart {
48namespace bin {
49
Ryan Macnakb46af1e2017-01-23 10:25:02 -080050// Snapshot pieces if we link in a snapshot, otherwise initialized to NULL.
Ryan Macnak14ec8fa2017-05-24 14:38:09 -070051#if defined(DART_NO_SNAPSHOT)
52const uint8_t* vm_snapshot_data = NULL;
53const uint8_t* vm_snapshot_instructions = NULL;
54const uint8_t* core_isolate_snapshot_data = NULL;
55const uint8_t* core_isolate_snapshot_instructions = NULL;
56#else
57const uint8_t* vm_snapshot_data = kDartVmSnapshotData;
58const uint8_t* vm_snapshot_instructions = kDartVmSnapshotInstructions;
59const uint8_t* core_isolate_snapshot_data = kDartCoreIsolateSnapshotData;
Ryan Macnak76df24b2017-05-31 13:49:09 -070060const uint8_t* core_isolate_snapshot_instructions =
61 kDartCoreIsolateSnapshotInstructions;
Ryan Macnak14ec8fa2017-05-24 14:38:09 -070062#endif
dgrove@google.com4c0f5592011-10-05 05:20:07 +000063
Siva Annamalai62b12f22016-02-05 15:28:59 -080064/**
65 * Global state used to control and store generation of application snapshots
Siva Annamalaiaf4d2462016-10-19 17:42:01 -070066 * An application snapshot can be generated and run using the following
67 * command
68 * dart --snapshot-kind=app-jit --snapshot=<app_snapshot_filename>
69 * <script_uri> [<script_options>]
70 * To Run the application snapshot generated above, use :
71 * dart <app_snapshot_filename> [<script_options>]
Siva Annamalai62b12f22016-02-05 15:28:59 -080072 */
Ryan Macnak26a364f2017-01-17 15:59:41 -080073static bool vm_run_app_snapshot = false;
zra@google.com0f6c47ab2014-09-08 20:52:25 +000074static const char* snapshot_filename = NULL;
Ryan Macnak7546ef12016-05-06 12:40:04 -070075enum SnapshotKind {
76 kNone,
77 kScript,
78 kAppAOT,
Siva Annamalaiaf4d2462016-10-19 17:42:01 -070079 kAppJIT,
Ryan Macnak7546ef12016-05-06 12:40:04 -070080};
81static SnapshotKind gen_snapshot_kind = kNone;
P.Y. Laligand8f035202017-03-27 06:44:21 -070082static const char* snapshot_deps_filename = NULL;
Siva Annamalai286dd512017-05-25 15:40:36 -070083#if !defined(DART_PRECOMPILED_RUNTIME)
84DFE dfe;
85#endif
Kevin Millikin385f8fb2017-04-25 20:04:20 +020086
Ryan Macnak74f3d1b2017-06-05 16:56:16 -070087// Value of the --save-compilation-trace flag.
88// (This pointer points into an argv buffer and does not need to be
89// free'd.)
90static const char* save_compilation_trace_filename = NULL;
91
92// Value of the --load-compilation-trace flag.
93// (This pointer points into an argv buffer and does not need to be
94// free'd.)
95static const char* load_compilation_trace_filename = NULL;
96
Ryan Macnak4607e382016-12-16 16:00:17 -080097// Value of the --save-feedback flag.
98// (This pointer points into an argv buffer and does not need to be
99// free'd.)
100static const char* save_feedback_filename = NULL;
101
102// Value of the --load-feedback flag.
103// (This pointer points into an argv buffer and does not need to be
104// free'd.)
105static const char* load_feedback_filename = NULL;
106
mattsh@google.comcb829912012-04-27 17:23:00 +0000107// Value of the --package-root flag.
108// (This pointer points into an argv buffer and does not need to be
109// free'd.)
ajohnsen@google.com0491f4e2014-09-23 05:46:14 +0000110static const char* commandline_package_root = NULL;
mattsh@google.comcb829912012-04-27 17:23:00 +0000111
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700112// Value of the --packages flag.
113// (This pointer points into an argv buffer and does not need to be
114// free'd.)
115static const char* commandline_packages_file = NULL;
116
asiva@google.combde808f2011-12-20 02:04:24 +0000117// Global flag that is used to indicate that we want to compile all the
118// dart functions and not run anything.
Siva Annamalai62b12f22016-02-05 15:28:59 -0800119static bool compile_all = false;
Siva Annamalai12f86592016-09-23 15:20:39 -0700120static bool parse_all = false;
asiva@google.combde808f2011-12-20 02:04:24 +0000121
Ryan Macnakf262fad2016-04-25 16:19:34 -0700122// Global flag that is used to indicate that we want to use blobs/mmap instead
123// of assembly/shared libraries for precompilation.
124static bool use_blobs = false;
125
Vyacheslav Egorov7d523172017-08-25 09:48:20 +0200126// Global flag is used to indicate that we want to obfuscate identifiers.
127static bool obfuscate = false;
128
129// Value of the --save-obfuscation-map= flag.
130static const char* obfuscation_map_filename = NULL;
131
iposva@google.comd0763f92015-05-11 22:58:32 +0000132// Global flag that is used to indicate that we want to trace resolution of
133// URIs and the loading of libraries, parts and scripts.
Siva Annamalai62b12f22016-02-05 15:28:59 -0800134static bool trace_loading = false;
asiva@google.com6b8987e2013-03-14 09:47:46 +0000135
Ryan Macnak26a364f2017-01-17 15:59:41 -0800136static char* app_script_uri = NULL;
Ryan Macnakb46af1e2017-01-23 10:25:02 -0800137static const uint8_t* app_isolate_snapshot_data = NULL;
138static const uint8_t* app_isolate_snapshot_instructions = NULL;
Ryan Macnak26a364f2017-01-17 15:59:41 -0800139
Ryan Macnak4d65db8a2016-10-31 15:56:25 -0700140static Dart_Isolate main_isolate = NULL;
141
Ryan Macnak1b518892016-11-23 14:24:52 -0800142static const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
johnmccutchan@google.com164a35002014-06-17 14:26:38 +0000143static const int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +0000144// VM Service options.
johnmccutchan@google.com164a35002014-06-17 14:26:38 +0000145static const char* vm_service_server_ip = DEFAULT_VM_SERVICE_SERVER_IP;
146// The 0 port is a magic value which results in the first available port
147// being allocated.
johnmccutchan@google.com435c6ad2014-09-10 22:38:33 +0000148static int vm_service_server_port = -1;
John McCutchanaf854322016-07-07 12:14:54 -0700149// True when we are running in development mode and cross origin security
150// checks are disabled.
151static bool vm_service_dev_mode = false;
iposva@google.comc859d252015-02-05 14:30:24 +0000152
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000153// The environment provided through the command line using -D options.
154static dart::HashMap* environment = NULL;
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +0000155
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000156static bool IsValidFlag(const char* name,
157 const char* prefix,
158 intptr_t prefix_length) {
159 intptr_t name_length = strlen(name);
160 return ((name_length > prefix_length) &&
161 (strncmp(name, prefix, prefix_length) == 0));
162}
163
Siva Annamalai62b12f22016-02-05 15:28:59 -0800164static bool version_option = false;
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000165static bool ProcessVersionOption(const char* arg,
166 CommandLineOptions* vm_options) {
iposva@google.combc268002012-10-11 07:17:09 +0000167 if (*arg != '\0') {
168 return false;
169 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800170 version_option = true;
iposva@google.combc268002012-10-11 07:17:09 +0000171 return true;
172}
173
Siva Annamalai62b12f22016-02-05 15:28:59 -0800174static bool help_option = false;
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000175static bool ProcessHelpOption(const char* arg, CommandLineOptions* vm_options) {
iposva@google.comd3f5b602012-09-24 22:26:37 +0000176 if (*arg != '\0') {
177 return false;
178 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800179 help_option = true;
iposva@google.comd3f5b602012-09-24 22:26:37 +0000180 return true;
181}
182
Siva Annamalai62b12f22016-02-05 15:28:59 -0800183static bool verbose_option = false;
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000184static bool ProcessVerboseOption(const char* arg,
185 CommandLineOptions* vm_options) {
iposva@google.comd3f5b602012-09-24 22:26:37 +0000186 if (*arg != '\0') {
187 return false;
188 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800189 verbose_option = true;
iposva@google.comd3f5b602012-09-24 22:26:37 +0000190 return true;
191}
192
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000193static bool ProcessPackageRootOption(const char* arg,
194 CommandLineOptions* vm_options) {
mattsh@google.comcb829912012-04-27 17:23:00 +0000195 ASSERT(arg != NULL);
Matthias Hausnera71a6fc2016-06-20 15:41:54 -0700196 if (*arg == '-') {
asiva@google.coma12382d2013-06-10 21:57:49 +0000197 return false;
198 }
ajohnsen@google.com0491f4e2014-09-23 05:46:14 +0000199 commandline_package_root = arg;
iposva@google.comd3f5b602012-09-24 22:26:37 +0000200 return true;
mattsh@google.comcb829912012-04-27 17:23:00 +0000201}
202
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700203static bool ProcessPackagesOption(const char* arg,
Matthias Hausnera71a6fc2016-06-20 15:41:54 -0700204 CommandLineOptions* vm_options) {
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700205 ASSERT(arg != NULL);
Matthias Hausnera71a6fc2016-06-20 15:41:54 -0700206 if (*arg == '-') {
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700207 return false;
208 }
209 commandline_packages_file = arg;
210 return true;
211}
212
Ryan Macnak74f3d1b2017-06-05 16:56:16 -0700213static bool ProcessSaveCompilationTraceOption(const char* arg,
214 CommandLineOptions* vm_options) {
215 ASSERT(arg != NULL);
216 if (*arg == '-') {
217 return false;
218 }
219 save_compilation_trace_filename = arg;
220 return true;
221}
222
Ryan Macnak74f3d1b2017-06-05 16:56:16 -0700223static bool ProcessLoadCompilationTraceOption(const char* arg,
224 CommandLineOptions* vm_options) {
225 ASSERT(arg != NULL);
226 if (*arg == '-') {
227 return false;
228 }
229 load_compilation_trace_filename = arg;
230 return true;
231}
232
Ryan Macnak4607e382016-12-16 16:00:17 -0800233static bool ProcessSaveFeedbackOption(const char* arg,
234 CommandLineOptions* vm_options) {
235 ASSERT(arg != NULL);
236 if (*arg == '-') {
237 return false;
238 }
239 save_feedback_filename = arg;
240 return true;
241}
242
Ryan Macnak4607e382016-12-16 16:00:17 -0800243static bool ProcessLoadFeedbackOption(const char* arg,
244 CommandLineOptions* vm_options) {
245 ASSERT(arg != NULL);
246 if (*arg == '-') {
247 return false;
248 }
249 load_feedback_filename = arg;
250 return true;
251}
252
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000253static void* GetHashmapKeyFromString(char* key) {
254 return reinterpret_cast<void*>(key);
255}
256
Ryan Macnak1b518892016-11-23 14:24:52 -0800257static bool ExtractPortAndAddress(const char* option_value,
258 int* out_port,
259 const char** out_ip,
260 int default_port,
261 const char* default_ip) {
kustermann@google.comebd83172014-04-23 13:09:10 +0000262 // [option_value] has to be one of the following formats:
263 // - ""
264 // - ":8181"
265 // - "=8181"
266 // - ":8181/192.168.0.1"
267 // - "=8181/192.168.0.1"
Ryan Macnak1b518892016-11-23 14:24:52 -0800268 // - "=8181/::1"
kustermann@google.comebd83172014-04-23 13:09:10 +0000269
Zachary Anderson479a97b2016-11-04 12:30:56 -0700270 if (*option_value == '\0') {
kustermann@google.comebd83172014-04-23 13:09:10 +0000271 *out_ip = default_ip;
272 *out_port = default_port;
273 return true;
274 }
275
276 if ((*option_value != '=') && (*option_value != ':')) {
277 return false;
278 }
279
280 int port = atoi(option_value + 1);
Zachary Anderson479a97b2016-11-04 12:30:56 -0700281 const char* slash = strstr(option_value, "/");
kustermann@google.comebd83172014-04-23 13:09:10 +0000282 if (slash == NULL) {
283 *out_ip = default_ip;
284 *out_port = port;
285 return true;
286 }
287
Ryan Macnak1b518892016-11-23 14:24:52 -0800288 *out_ip = slash + 1;
289 *out_port = port;
290 return true;
kustermann@google.comebd83172014-04-23 13:09:10 +0000291}
292
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000293static bool ProcessEnvironmentOption(const char* arg,
294 CommandLineOptions* vm_options) {
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000295 ASSERT(arg != NULL);
296 if (*arg == '\0') {
297 // Ignore empty -D option.
Siva Annamalaiaae051e2016-10-12 18:42:30 -0700298 Log::PrintErr("No arguments given to -D option, ignoring it\n");
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000299 return true;
300 }
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000301 // Split the name=value part of the -Dname=value argument.
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000302 const char* equals_pos = strchr(arg, '=');
303 if (equals_pos == NULL) {
304 // No equal sign (name without value) currently not supported.
Siva Annamalaiaae051e2016-10-12 18:42:30 -0700305 Log::PrintErr("No value given in -D%s option, ignoring it\n", arg);
306 return true;
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000307 }
Zachary Anderson82cb63e2016-08-08 12:53:26 -0700308
309 char* name;
310 char* value = NULL;
311 int name_len = equals_pos - arg;
312 if (name_len == 0) {
Siva Annamalaiaae051e2016-10-12 18:42:30 -0700313 Log::PrintErr("No name given in -D%s option, ignoring it\n", arg);
314 return true;
Zachary Anderson82cb63e2016-08-08 12:53:26 -0700315 }
316 // Split name=value into name and value.
317 name = reinterpret_cast<char*>(malloc(name_len + 1));
318 strncpy(name, arg, name_len);
319 name[name_len] = '\0';
320 value = strdup(equals_pos + 1);
Siva Annamalaiaae051e2016-10-12 18:42:30 -0700321 if (environment == NULL) {
322 environment = new HashMap(&HashMap::SameStringValue, 4);
323 }
Zachary Anderson479a97b2016-11-04 12:30:56 -0700324 HashMap::Entry* entry = environment->Lookup(GetHashmapKeyFromString(name),
325 HashMap::StringHash(name), true);
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000326 ASSERT(entry != NULL); // Lookup adds an entry if key not found.
Zachary Anderson82cb63e2016-08-08 12:53:26 -0700327 if (entry->value != NULL) {
328 free(name);
329 free(entry->value);
330 }
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000331 entry->value = value;
332 return true;
333}
334
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000335static bool ProcessCompileAllOption(const char* arg,
336 CommandLineOptions* vm_options) {
iposva@google.comd3f5b602012-09-24 22:26:37 +0000337 ASSERT(arg != NULL);
338 if (*arg != '\0') {
339 return false;
340 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800341 compile_all = true;
iposva@google.comd3f5b602012-09-24 22:26:37 +0000342 return true;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000343}
344
Siva Annamalai12f86592016-09-23 15:20:39 -0700345static bool ProcessParseAllOption(const char* arg,
346 CommandLineOptions* vm_options) {
347 ASSERT(arg != NULL);
348 if (*arg != '\0') {
349 return false;
350 }
351 parse_all = true;
352 return true;
353}
354
Siva Annamalai286dd512017-05-25 15:40:36 -0700355#if !defined(DART_PRECOMPILED_RUNTIME)
Matthias Hausnerf5ab1732016-12-07 09:11:16 -0800356static bool ProcessFrontendOption(const char* filename,
357 CommandLineOptions* vm_options) {
358 ASSERT(filename != NULL);
359 if (filename[0] == '\0') {
360 return false;
361 }
Siva Annamalai286dd512017-05-25 15:40:36 -0700362 dfe.set_frontend_filename(filename);
Matthias Hausnerf5ab1732016-12-07 09:11:16 -0800363 return true;
364}
365
Siva Chandrabac83e02017-06-16 12:22:28 -0700366static bool ProcessKernelBinariesOption(const char* dirname,
367 CommandLineOptions* vm_options) {
368 ASSERT(dirname != NULL);
369 if (dirname[0] == '\0') {
Kevin Millikin385f8fb2017-04-25 20:04:20 +0200370 return false;
371 }
Siva Chandrabac83e02017-06-16 12:22:28 -0700372 dfe.SetKernelBinaries(dirname);
Kevin Millikin385f8fb2017-04-25 20:04:20 +0200373 return true;
374}
Siva Annamalai286dd512017-05-25 15:40:36 -0700375#endif
Kevin Millikin385f8fb2017-04-25 20:04:20 +0200376
Ryan Macnakf262fad2016-04-25 16:19:34 -0700377static bool ProcessUseBlobsOption(const char* arg,
378 CommandLineOptions* vm_options) {
379 ASSERT(arg != NULL);
380 if (*arg != '\0') {
381 return false;
382 }
383 use_blobs = true;
384 return true;
385}
386
Vyacheslav Egorov7d523172017-08-25 09:48:20 +0200387static bool ProcessObfuscateOption(const char* arg,
388 CommandLineOptions* vm_options) {
389 ASSERT(arg != NULL);
390 if (*arg != '\0') {
391 return false;
392 }
393 obfuscate = true;
394 return true;
395}
396
397static bool ProcessObfuscationMapFilenameOption(
398 const char* filename,
399 CommandLineOptions* vm_options) {
400 obfuscation_map_filename = filename;
401 return true;
402}
403
Ryan Macnak7546ef12016-05-06 12:40:04 -0700404static bool ProcessSnapshotFilenameOption(const char* filename,
405 CommandLineOptions* vm_options) {
Siva Annamalai62b12f22016-02-05 15:28:59 -0800406 snapshot_filename = filename;
Ryan Macnak7546ef12016-05-06 12:40:04 -0700407 if (gen_snapshot_kind == kNone) {
408 gen_snapshot_kind = kScript; // Default behavior.
asiva@google.com29171992012-09-04 20:46:30 +0000409 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800410 return true;
asiva@google.com29171992012-09-04 20:46:30 +0000411}
412
Ryan Macnak7546ef12016-05-06 12:40:04 -0700413static bool ProcessSnapshotKindOption(const char* kind,
414 CommandLineOptions* vm_options) {
415 if (strcmp(kind, "script") == 0) {
416 gen_snapshot_kind = kScript;
417 return true;
418 } else if (strcmp(kind, "app-aot") == 0) {
419 gen_snapshot_kind = kAppAOT;
420 return true;
Siva Annamalaiaf4d2462016-10-19 17:42:01 -0700421 } else if (strcmp(kind, "app-jit") == 0) {
422 gen_snapshot_kind = kAppJIT;
Ryan Macnak7546ef12016-05-06 12:40:04 -0700423 return true;
Siva Annamalai62b12f22016-02-05 15:28:59 -0800424 }
Zachary Anderson479a97b2016-11-04 12:30:56 -0700425 Log::PrintErr(
426 "Unrecognized snapshot kind: '%s'\nValid kinds are: "
427 "script, app-aot, app-jit\n",
428 kind);
Siva Annamalai809c2052016-02-22 15:33:34 -0800429 return false;
Ryan Macnak7546ef12016-05-06 12:40:04 -0700430}
431
P.Y. Laligand8f035202017-03-27 06:44:21 -0700432static bool ProcessSnapshotDepsFilenameOption(const char* filename,
433 CommandLineOptions* vm_options) {
434 snapshot_deps_filename = filename;
435 return true;
436}
437
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000438static bool ProcessEnableVmServiceOption(const char* option_value,
439 CommandLineOptions* vm_options) {
kustermann@google.comebd83172014-04-23 13:09:10 +0000440 ASSERT(option_value != NULL);
441
Ryan Macnak1b518892016-11-23 14:24:52 -0800442 if (!ExtractPortAndAddress(
443 option_value, &vm_service_server_port, &vm_service_server_ip,
444 DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700445 Log::PrintErr(
446 "unrecognized --enable-vm-service option syntax. "
Ryan Macnak1b518892016-11-23 14:24:52 -0800447 "Use --enable-vm-service[=<port number>[/<bind address>]]\n");
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +0000448 return false;
449 }
kustermann@google.comebd83172014-04-23 13:09:10 +0000450
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +0000451 return true;
452}
453
John McCutchanaf854322016-07-07 12:14:54 -0700454static bool ProcessDisableServiceOriginCheckOption(
Zachary Anderson479a97b2016-11-04 12:30:56 -0700455 const char* option_value,
456 CommandLineOptions* vm_options) {
John McCutchanaf854322016-07-07 12:14:54 -0700457 ASSERT(option_value != NULL);
Zachary Anderson479a97b2016-11-04 12:30:56 -0700458 Log::PrintErr(
459 "WARNING: You are running with the service protocol in an "
460 "insecure mode.\n");
John McCutchanaf854322016-07-07 12:14:54 -0700461 vm_service_dev_mode = true;
462 return true;
463}
464
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000465static bool ProcessObserveOption(const char* option_value,
466 CommandLineOptions* vm_options) {
467 ASSERT(option_value != NULL);
468
Ryan Macnak1b518892016-11-23 14:24:52 -0800469 if (!ExtractPortAndAddress(
470 option_value, &vm_service_server_port, &vm_service_server_ip,
471 DEFAULT_VM_SERVICE_SERVER_PORT, DEFAULT_VM_SERVICE_SERVER_IP)) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700472 Log::PrintErr(
473 "unrecognized --observe option syntax. "
Ryan Macnak1b518892016-11-23 14:24:52 -0800474 "Use --observe[=<port number>[/<bind address>]]\n");
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000475 return false;
476 }
johnmccutchan@google.com2acd1f82014-05-27 07:40:17 +0000477
Todd Turnidgebd3cdf42016-05-13 10:51:51 -0700478 // These options should also be documented in the help message.
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000479 vm_options->AddArgument("--pause-isolates-on-exit");
Todd Turnidge0f1d73f2016-01-29 12:19:33 -0800480 vm_options->AddArgument("--pause-isolates-on-unhandled-exceptions");
Ryan Macnakf8e47a92017-08-09 11:20:55 -0700481 vm_options->AddArgument("--profiler");
Todd Turnidge0f1d73f2016-01-29 12:19:33 -0800482 vm_options->AddArgument("--warn-on-pause-with-no-debugger");
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000483 return true;
484}
485
iposva@google.comd0763f92015-05-11 22:58:32 +0000486static bool ProcessTraceLoadingOption(const char* arg,
487 CommandLineOptions* vm_options) {
488 if (*arg != '\0') {
489 return false;
490 }
Siva Annamalai62b12f22016-02-05 15:28:59 -0800491 trace_loading = true;
iposva@google.comd0763f92015-05-11 22:58:32 +0000492 return true;
493}
494
John McCutchan621ce4e2016-07-01 14:26:25 -0700495static bool ProcessHotReloadTestModeOption(const char* arg,
496 CommandLineOptions* vm_options) {
497 if (*arg != '\0') {
498 return false;
499 }
500
501 // Identity reload.
502 vm_options->AddArgument("--identity_reload");
503 // Start reloading quickly.
John McCutchand0ebc782016-07-25 13:34:04 -0700504 vm_options->AddArgument("--reload_every=4");
John McCutchan621ce4e2016-07-01 14:26:25 -0700505 // Reload from optimized and unoptimized code.
506 vm_options->AddArgument("--reload_every_optimized=false");
507 // Reload less frequently as time goes on.
508 vm_options->AddArgument("--reload_every_back_off");
John McCutchanef71bc12016-07-11 12:29:13 -0700509 // Ensure that every isolate has reloaded once before exiting.
John McCutchan621ce4e2016-07-01 14:26:25 -0700510 vm_options->AddArgument("--check_reloaded");
511
512 return true;
513}
514
John McCutchan9c83d2462016-08-01 10:57:22 -0700515static bool ProcessHotReloadRollbackTestModeOption(
Zachary Anderson479a97b2016-11-04 12:30:56 -0700516 const char* arg,
517 CommandLineOptions* vm_options) {
John McCutchan9c83d2462016-08-01 10:57:22 -0700518 // Identity reload.
519 vm_options->AddArgument("--identity_reload");
520 // Start reloading quickly.
521 vm_options->AddArgument("--reload_every=4");
522 // Reload from optimized and unoptimized code.
523 vm_options->AddArgument("--reload_every_optimized=false");
524 // Reload less frequently as time goes on.
525 vm_options->AddArgument("--reload_every_back_off");
526 // Ensure that every isolate has reloaded once before exiting.
527 vm_options->AddArgument("--check_reloaded");
528 // Force all reloads to fail and execute the rollback code.
529 vm_options->AddArgument("--reload_force_rollback");
530
531 return true;
532}
533
Florian Schneider021ebb202016-08-15 18:28:11 -0700534extern bool short_socket_read;
535
536extern bool short_socket_write;
537
538static bool ProcessShortSocketReadOption(const char* arg,
539 CommandLineOptions* vm_options) {
540 short_socket_read = true;
541 return true;
542}
543
Florian Schneider021ebb202016-08-15 18:28:11 -0700544static bool ProcessShortSocketWriteOption(const char* arg,
545 CommandLineOptions* vm_options) {
546 short_socket_write = true;
547 return true;
548}
549
Zachary Anderson139db222016-09-16 09:08:51 -0700550extern const char* commandline_root_certs_file;
551extern const char* commandline_root_certs_cache;
552
553static bool ProcessRootCertsFileOption(const char* arg,
554 CommandLineOptions* vm_options) {
555 ASSERT(arg != NULL);
556 if (*arg == '-') {
557 return false;
558 }
559 if (commandline_root_certs_cache != NULL) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700560 Log::PrintErr(
561 "Only one of --root-certs-file and --root-certs-cache "
562 "may be specified");
Zachary Anderson139db222016-09-16 09:08:51 -0700563 return false;
564 }
565 commandline_root_certs_file = arg;
566 return true;
567}
568
Zachary Anderson139db222016-09-16 09:08:51 -0700569static bool ProcessRootCertsCacheOption(const char* arg,
Zachary Anderson479a97b2016-11-04 12:30:56 -0700570 CommandLineOptions* vm_options) {
Zachary Anderson139db222016-09-16 09:08:51 -0700571 ASSERT(arg != NULL);
572 if (*arg == '-') {
573 return false;
574 }
575 if (commandline_root_certs_file != NULL) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700576 Log::PrintErr(
577 "Only one of --root-certs-file and --root-certs-cache "
578 "may be specified");
Zachary Anderson139db222016-09-16 09:08:51 -0700579 return false;
580 }
581 commandline_root_certs_cache = arg;
582 return true;
583}
Zachary Anderson139db222016-09-16 09:08:51 -0700584
asiva@google.combde808f2011-12-20 02:04:24 +0000585static struct {
586 const char* option_name;
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000587 bool (*process)(const char* option, CommandLineOptions* vm_options);
asiva@google.combde808f2011-12-20 02:04:24 +0000588} main_options[] = {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700589 // Standard options shared with dart2js.
590 {"-D", ProcessEnvironmentOption},
591 {"-h", ProcessHelpOption},
592 {"--help", ProcessHelpOption},
593 {"--packages=", ProcessPackagesOption},
594 {"--package-root=", ProcessPackageRootOption},
595 {"-v", ProcessVerboseOption},
596 {"--verbose", ProcessVerboseOption},
597 {"--version", ProcessVersionOption},
Zachary Anderson7093f292015-09-15 12:49:52 -0700598
Zachary Anderson479a97b2016-11-04 12:30:56 -0700599 // VM specific options to the standalone dart program.
600 {"--compile_all", ProcessCompileAllOption},
601 {"--parse_all", ProcessParseAllOption},
Siva Annamalai286dd512017-05-25 15:40:36 -0700602#if !defined(DART_PRECOMPILED_RUNTIME)
Matthias Hausnerf5ab1732016-12-07 09:11:16 -0800603 {"--dfe=", ProcessFrontendOption},
Siva Chandrabac83e02017-06-16 12:22:28 -0700604 {"--kernel-binaries=", ProcessKernelBinariesOption},
Siva Annamalai286dd512017-05-25 15:40:36 -0700605#endif
Zachary Anderson479a97b2016-11-04 12:30:56 -0700606 {"--enable-vm-service", ProcessEnableVmServiceOption},
607 {"--disable-service-origin-check", ProcessDisableServiceOriginCheckOption},
608 {"--observe", ProcessObserveOption},
609 {"--snapshot=", ProcessSnapshotFilenameOption},
610 {"--snapshot-kind=", ProcessSnapshotKindOption},
P.Y. Laligand8f035202017-03-27 06:44:21 -0700611 {"--snapshot-depfile=", ProcessSnapshotDepsFilenameOption},
Zachary Anderson479a97b2016-11-04 12:30:56 -0700612 {"--use-blobs", ProcessUseBlobsOption},
Vyacheslav Egorov7d523172017-08-25 09:48:20 +0200613 {"--obfuscate", ProcessObfuscateOption},
614 {"--save-obfuscation-map=", ProcessObfuscationMapFilenameOption},
Ryan Macnak74f3d1b2017-06-05 16:56:16 -0700615 {"--save-compilation-trace=", ProcessSaveCompilationTraceOption},
616 {"--load-compilation-trace=", ProcessLoadCompilationTraceOption},
Ryan Macnak4607e382016-12-16 16:00:17 -0800617 {"--save-feedback=", ProcessSaveFeedbackOption},
618 {"--load-feedback=", ProcessLoadFeedbackOption},
Zachary Anderson479a97b2016-11-04 12:30:56 -0700619 {"--trace-loading", ProcessTraceLoadingOption},
620 {"--hot-reload-test-mode", ProcessHotReloadTestModeOption},
621 {"--hot-reload-rollback-test-mode", ProcessHotReloadRollbackTestModeOption},
622 {"--short_socket_read", ProcessShortSocketReadOption},
623 {"--short_socket_write", ProcessShortSocketWriteOption},
Zachary Anderson479a97b2016-11-04 12:30:56 -0700624 {"--root-certs-file=", ProcessRootCertsFileOption},
625 {"--root-certs-cache=", ProcessRootCertsCacheOption},
Zachary Anderson479a97b2016-11-04 12:30:56 -0700626 {NULL, NULL}};
asiva@google.combde808f2011-12-20 02:04:24 +0000627
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000628static bool ProcessMainOptions(const char* option,
629 CommandLineOptions* vm_options) {
asiva@google.combde808f2011-12-20 02:04:24 +0000630 int i = 0;
631 const char* name = main_options[0].option_name;
asiva@google.coma12382d2013-06-10 21:57:49 +0000632 int option_length = strlen(option);
asiva@google.combde808f2011-12-20 02:04:24 +0000633 while (name != NULL) {
634 int length = strlen(name);
asiva@google.coma12382d2013-06-10 21:57:49 +0000635 if ((option_length >= length) && (strncmp(option, name, length) == 0)) {
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000636 if (main_options[i].process(option + length, vm_options)) {
ajohnsen@google.com8bd58482013-06-11 11:55:43 +0000637 return true;
asiva@google.coma12382d2013-06-10 21:57:49 +0000638 }
asiva@google.combde808f2011-12-20 02:04:24 +0000639 }
640 i += 1;
641 name = main_options[i].option_name;
hausner@google.com91593892011-12-07 22:13:49 +0000642 }
asiva@google.combde808f2011-12-20 02:04:24 +0000643 return false;
hausner@google.com91593892011-12-07 22:13:49 +0000644}
645
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000646// Parse out the command line arguments. Returns -1 if the arguments
647// are incorrect, 0 otherwise.
648static int ParseArguments(int argc,
649 char** argv,
650 CommandLineOptions* vm_options,
651 char** script_name,
asiva@google.comc7f58ad2012-06-13 17:48:47 +0000652 CommandLineOptions* dart_options,
tball@google.comb3cae062013-04-05 20:55:10 +0000653 bool* print_flags_seen,
654 bool* verbose_debug_seen) {
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000655 const char* kPrefix = "--";
656 const intptr_t kPrefixLen = strlen(kPrefix);
657
sgjesse@google.coma1158d62013-08-08 07:19:21 +0000658 // Store the executable name.
659 Platform::SetExecutableName(argv[0]);
ager@google.com16ee3e92012-05-07 14:27:05 +0000660
661 // Start the rest after the executable name.
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000662 int i = 1;
663
664 // Parse out the vm options.
iposva@google.comd3f5b602012-09-24 22:26:37 +0000665 while (i < argc) {
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000666 if (ProcessMainOptions(argv[i], vm_options)) {
ager@google.com8a677912012-05-08 06:41:00 +0000667 i++;
hausner@google.com91593892011-12-07 22:13:49 +0000668 } else {
iposva@google.comd3f5b602012-09-24 22:26:37 +0000669 // Check if this flag is a potentially valid VM flag.
asiva@google.coma12382d2013-06-10 21:57:49 +0000670 const char* kChecked = "-c";
671 const char* kPackageRoot = "-p";
672 if (strncmp(argv[i], kPackageRoot, strlen(kPackageRoot)) == 0) {
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000673 if (!ProcessPackageRootOption(argv[i] + strlen(kPackageRoot),
674 vm_options)) {
asiva@google.coma12382d2013-06-10 21:57:49 +0000675 i++;
johnmccutchan@google.comc57e2b02014-05-27 07:26:05 +0000676 if ((argv[i] == NULL) ||
Zachary Anderson479a97b2016-11-04 12:30:56 -0700677 !ProcessPackageRootOption(argv[i], vm_options)) {
asiva@google.coma12382d2013-06-10 21:57:49 +0000678 Log::PrintErr("Invalid option specification : '%s'\n", argv[i - 1]);
679 i++;
680 break;
681 }
682 }
asiva@google.com85730432014-06-19 21:00:50 +0000683 i++;
684 continue; // '-p' is not a VM flag so don't add to vm options.
asiva@google.coma12382d2013-06-10 21:57:49 +0000685 } else if (strncmp(argv[i], kChecked, strlen(kChecked)) == 0) {
686 vm_options->AddArgument("--checked");
asiva@google.com85730432014-06-19 21:00:50 +0000687 i++;
688 continue; // '-c' is not a VM flag so don't add to vm options.
asiva@google.coma12382d2013-06-10 21:57:49 +0000689 } else if (!IsValidFlag(argv[i], kPrefix, kPrefixLen)) {
iposva@google.comd3f5b602012-09-24 22:26:37 +0000690 break;
691 }
asiva@google.com85730432014-06-19 21:00:50 +0000692 // The following two flags are processed by both the embedder and
693 // the VM.
asiva@google.comc7f58ad2012-06-13 17:48:47 +0000694 const char* kPrintFlags1 = "--print-flags";
695 const char* kPrintFlags2 = "--print_flags";
asiva@google.com85730432014-06-19 21:00:50 +0000696 const char* kVerboseDebug1 = "--verbose_debug";
697 const char* kVerboseDebug2 = "--verbose-debug";
asiva@google.comc7f58ad2012-06-13 17:48:47 +0000698 if ((strncmp(argv[i], kPrintFlags1, strlen(kPrintFlags1)) == 0) ||
699 (strncmp(argv[i], kPrintFlags2, strlen(kPrintFlags2)) == 0)) {
700 *print_flags_seen = true;
Zachary Anderson479a97b2016-11-04 12:30:56 -0700701 } else if ((strncmp(argv[i], kVerboseDebug1, strlen(kVerboseDebug1)) ==
702 0) ||
703 (strncmp(argv[i], kVerboseDebug2, strlen(kVerboseDebug2)) ==
704 0)) {
tball@google.comb3cae062013-04-05 20:55:10 +0000705 *verbose_debug_seen = true;
706 }
hausner@google.com91593892011-12-07 22:13:49 +0000707 vm_options->AddArgument(argv[i]);
ager@google.com8a677912012-05-08 06:41:00 +0000708 i++;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000709 }
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000710 }
cshapiro@google.com772a3992012-07-26 00:21:25 +0000711
whesse@google.com9de122a2013-08-21 15:21:55 +0000712 // The arguments to the VM are at positions 1 through i-1 in argv.
713 Platform::SetExecutableArguments(i, argv);
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000714
715 // Get the script name.
716 if (i < argc) {
717 *script_name = argv[i];
ager@google.com8a677912012-05-08 06:41:00 +0000718 i++;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000719 } else {
720 return -1;
721 }
722
723 // Parse out options to be passed to dart main.
724 while (i < argc) {
725 dart_options->AddArgument(argv[i]);
ager@google.com8a677912012-05-08 06:41:00 +0000726 i++;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000727 }
728
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700729 // Verify consistency of arguments.
730 if ((commandline_package_root != NULL) &&
731 (commandline_packages_file != NULL)) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700732 Log::PrintErr(
733 "Specifying both a packages directory and a packages "
734 "file is invalid.\n");
Ryan Macnak9328d722016-01-08 10:19:14 -0800735 return -1;
736 }
Matthias Hausnera71a6fc2016-06-20 15:41:54 -0700737 if ((commandline_package_root != NULL) &&
738 (strlen(commandline_package_root) == 0)) {
739 Log::PrintErr("Empty package root specified.\n");
740 return -1;
741 }
742 if ((commandline_packages_file != NULL) &&
743 (strlen(commandline_packages_file) == 0)) {
744 Log::PrintErr("Empty package file name specified.\n");
745 return -1;
746 }
P.Y. Laligand8f035202017-03-27 06:44:21 -0700747 if (((gen_snapshot_kind != kNone) || (snapshot_deps_filename != NULL)) &&
748 (snapshot_filename == NULL)) {
Ryan Macnak7546ef12016-05-06 12:40:04 -0700749 Log::PrintErr("Generating a snapshot requires a filename (--snapshot).\n");
750 return -1;
751 }
Ryan Macnak26a364f2017-01-17 15:59:41 -0800752 if ((gen_snapshot_kind != kNone) && vm_run_app_snapshot) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700753 Log::PrintErr(
754 "Specifying an option to generate a snapshot and"
755 " run using a snapshot is invalid.\n");
Siva Annamalai62b12f22016-02-05 15:28:59 -0800756 return -1;
757 }
Ivan Posvab07a9dd2015-07-29 11:30:33 -0700758
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000759 return 0;
760}
761
iposva@google.com736d0342013-10-17 21:59:46 +0000762static Dart_Handle CreateRuntimeOptions(CommandLineOptions* options) {
iposva@google.com97634fb2011-11-03 21:45:03 +0000763 int options_count = options->count();
ager@google.com68166662011-11-04 12:25:53 +0000764 Dart_Handle dart_arguments = Dart_NewList(options_count);
turnidge@google.com8c64adf2011-11-11 19:31:04 +0000765 if (Dart_IsError(dart_arguments)) {
iposva@google.com97634fb2011-11-03 21:45:03 +0000766 return dart_arguments;
767 }
768 for (int i = 0; i < options_count; i++) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700769 Dart_Handle argument_value = DartUtils::NewString(options->GetArgument(i));
turnidge@google.com8c64adf2011-11-11 19:31:04 +0000770 if (Dart_IsError(argument_value)) {
iposva@google.com97634fb2011-11-03 21:45:03 +0000771 return argument_value;
772 }
ager@google.com68166662011-11-04 12:25:53 +0000773 Dart_Handle result = Dart_ListSetAt(dart_arguments, i, argument_value);
turnidge@google.com8c64adf2011-11-11 19:31:04 +0000774 if (Dart_IsError(result)) {
iposva@google.com97634fb2011-11-03 21:45:03 +0000775 return result;
776 }
777 }
iposva@google.com736d0342013-10-17 21:59:46 +0000778 return dart_arguments;
779}
780
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000781static Dart_Handle EnvironmentCallback(Dart_Handle name) {
782 uint8_t* utf8_array;
783 intptr_t utf8_len;
784 Dart_Handle result = Dart_Null();
785 Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
786 if (Dart_IsError(handle)) {
787 handle = Dart_ThrowException(
788 DartUtils::NewDartArgumentError(Dart_GetError(handle)));
789 } else {
790 char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
791 memmove(name_chars, utf8_array, utf8_len);
792 name_chars[utf8_len] = '\0';
793 const char* value = NULL;
794 if (environment != NULL) {
Zachary Anderson479a97b2016-11-04 12:30:56 -0700795 HashMap::Entry* entry =
796 environment->Lookup(GetHashmapKeyFromString(name_chars),
797 HashMap::StringHash(name_chars), false);
sgjesse@google.com36a67fa2013-10-31 05:46:57 +0000798 if (entry != NULL) {
799 value = reinterpret_cast<char*>(entry->value);
800 }
801 }
802 if (value != NULL) {
803 result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
804 strlen(value));
805 }
806 free(name_chars);
807 }
808 return result;
809}
810
Siva Chandra8b405072017-06-22 10:10:42 -0700811#define SAVE_ERROR_AND_EXIT(result) \
812 *error = strdup(Dart_GetError(result)); \
813 if (Dart_IsCompilationError(result)) { \
814 *exit_code = kCompilationErrorExitCode; \
815 } else if (Dart_IsApiError(result)) { \
816 *exit_code = kApiErrorExitCode; \
817 } else { \
818 *exit_code = kErrorExitCode; \
819 } \
820 Dart_ExitScope(); \
821 Dart_ShutdownIsolate(); \
822 return NULL;
823
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +0000824#define CHECK_RESULT(result) \
825 if (Dart_IsError(result)) { \
Siva Chandra8b405072017-06-22 10:10:42 -0700826 SAVE_ERROR_AND_EXIT(result); \
827 }
828
Siva Chandra8b405072017-06-22 10:10:42 -0700829#define CHECK_RESULT_CLEANUP(result, cleanup) \
830 if (Dart_IsError(result)) { \
831 delete (cleanup); \
832 SAVE_ERROR_AND_EXIT(result); \
Zachary Anderson479a97b2016-11-04 12:30:56 -0700833 }
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +0000834
Ryan Macnak6500f6e2017-02-13 11:17:31 -0800835static void SnapshotOnExitHook(int64_t exit_code) {
836 if (Dart_CurrentIsolate() != main_isolate) {
837 Log::PrintErr(
838 "A snapshot was requested, but a secondary isolate "
839 "performed a hard exit (%" Pd64 ").\n",
840 exit_code);
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800841 Platform::Exit(kErrorExitCode);
842 }
Ryan Macnak6500f6e2017-02-13 11:17:31 -0800843 if (exit_code == 0) {
844 Snapshot::GenerateAppJIT(snapshot_filename);
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800845 }
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800846}
847
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700848static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
849 bool is_main_isolate,
850 const char* script_uri,
851 const char* package_root,
852 const char* packages_config,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700853 bool set_native_resolvers,
854 bool isolate_run_app_snapshot,
855 char** error,
856 int* exit_code) {
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000857 Dart_EnterScope();
Siva Annamalai66564042017-06-07 13:42:17 -0700858 IsolateData* isolate_data =
859 reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
860 void* kernel_program = isolate_data->kernel_program;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000861
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100862 // Set up the library tag handler for this isolate.
863 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
864 CHECK_RESULT(result);
865
Siva Annamalai33c50e92017-07-19 18:09:17 -0700866 // Prepare builtin and other core libraries for use to resolve URIs.
867 // Set up various closures, e.g: printing, timers etc.
868 // Set up 'package root' for URI resolution.
869 result = DartUtils::PrepareForScriptLoading(false, trace_loading);
870 CHECK_RESULT(result);
871
Siva Annamalai53cf85a2017-07-27 10:06:52 -0700872#if !defined(DART_PRECOMPILED_RUNTIME)
873 if (dfe.kernel_file_specified()) {
Siva Annamalai000bec42017-07-21 08:27:37 -0700874 ASSERT(kernel_program != NULL);
875 result = Dart_LoadKernel(kernel_program);
Jens Johansenc7faf2d2017-08-14 10:38:11 +0200876 isolate_data->kernel_program = NULL; // Dart_LoadKernel takes ownership.
Siva Annamalai000bec42017-07-21 08:27:37 -0700877 } else {
878 if (kernel_program != NULL) {
879 Dart_Handle uri = Dart_NewStringFromCString(script_uri);
880 CHECK_RESULT(uri);
881 Dart_Handle resolved_script_uri = DartUtils::ResolveScript(uri);
882 CHECK_RESULT(resolved_script_uri);
883 result =
884 Dart_LoadScript(uri, resolved_script_uri,
885 reinterpret_cast<Dart_Handle>(kernel_program), 0, 0);
Jens Johansenc7faf2d2017-08-14 10:38:11 +0200886 isolate_data->kernel_program = NULL; // Dart_LoadScript takes ownership.
Siva Annamalai000bec42017-07-21 08:27:37 -0700887 CHECK_RESULT(result);
888 }
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100889 }
Siva Annamalai53cf85a2017-07-27 10:06:52 -0700890#endif // !defined(DART_PRECOMPILED_RUNTIME)
891
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700892 if (set_native_resolvers) {
iposva@google.com67b02b42012-03-07 22:57:57 +0000893 // Setup the native resolver as the snapshot does not carry it.
asiva@google.com6a0ea0d2012-09-08 01:00:28 +0000894 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
895 Builtin::SetNativeResolver(Builtin::kIOLibrary);
asiva@google.combde808f2011-12-20 02:04:24 +0000896 }
Ryan Macnak26a364f2017-01-17 15:59:41 -0800897 if (isolate_run_app_snapshot) {
Ryan Macnak987165f2016-11-07 16:17:47 -0800898 Dart_Handle result = Loader::ReloadNativeExtensions();
899 CHECK_RESULT(result);
900 }
iposva@google.com67b02b42012-03-07 22:57:57 +0000901
Florian Schneiderbef49672017-01-11 16:55:55 -0800902 // Set up the load port provided by the service isolate so that we can
903 // load scripts.
904 result = DartUtils::SetupServiceLoadPort();
905 CHECK_RESULT(result);
asiva@google.com29171992012-09-04 20:46:30 +0000906
Siva Annamalai1e5eab32016-02-04 09:18:31 -0800907 // Setup package root if specified.
908 result = DartUtils::SetupPackageRoot(package_root, packages_config);
asiva@google.com5858afd2013-03-21 18:47:49 +0000909 CHECK_RESULT(result);
asiva@google.com29171992012-09-04 20:46:30 +0000910
johnmccutchan@google.com172baa02015-01-29 18:31:27 +0000911 result = Dart_SetEnvironmentCallback(EnvironmentCallback);
912 CHECK_RESULT(result);
913
Ryan Macnak26a364f2017-01-17 15:59:41 -0800914 if (isolate_run_app_snapshot) {
Ryan Macnak257b3a82016-05-04 18:47:36 -0700915 result = DartUtils::SetupIOLibrary(script_uri);
916 CHECK_RESULT(result);
John McCutchanbf4b3b32016-06-07 12:47:44 -0700917 Loader::InitForSnapshot(script_uri);
Ryan Macnak26a364f2017-01-17 15:59:41 -0800918#if !defined(DART_PRECOMPILED_RUNTIME)
919 if (is_main_isolate) {
920 // Find the canonical uri of the app snapshot. We'll use this to decide if
921 // other isolates should use the app snapshot or the core snapshot.
922 const char* resolved_script_uri = NULL;
923 result = Dart_StringToCString(
924 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri)),
925 &resolved_script_uri);
926 CHECK_RESULT(result);
927 ASSERT(app_script_uri == NULL);
928 app_script_uri = strdup(resolved_script_uri);
929 }
930#endif // !defined(DART_PRECOMPILED_RUNTIME)
Ryan Macnak257b3a82016-05-04 18:47:36 -0700931 } else {
Siva Annamalai1e5eab32016-02-04 09:18:31 -0800932 // Load the specified application script into the newly created isolate.
John McCutchan6fd8fd72016-06-06 14:15:01 -0700933 Dart_Handle uri =
934 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
935 CHECK_RESULT(uri);
Kevin Millikind3fa66a2017-04-26 00:41:38 +0200936 if (kernel_program == NULL) {
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100937 result = Loader::LibraryTagHandler(Dart_kScriptTag, Dart_Null(), uri);
938 CHECK_RESULT(result);
Vyacheslav Egorov43a05002017-01-30 20:52:59 +0100939 } else {
940 // Various core-library parts will send requests to the Loader to resolve
941 // relative URIs and perform other related tasks. We need Loader to be
942 // initialized for this to work because loading from Kernel binary
943 // bypasses normal source code loading paths that initialize it.
944 Loader::InitForSnapshot(script_uri);
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100945 }
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +0000946
Zachary Anderson479a97b2016-11-04 12:30:56 -0700947 Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
948 Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
949 NULL, NULL);
Ryan Macnak9764a9f2015-09-16 11:22:57 -0700950
Ryan Macnak9764a9f2015-09-16 11:22:57 -0700951 result = DartUtils::SetupIOLibrary(script_uri);
952 CHECK_RESULT(result);
John McCutchan1ff71442015-08-18 15:18:02 -0700953 }
954
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000955 // Make the isolate runnable so that it is ready to handle messages.
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000956 Dart_ExitScope();
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000957 Dart_ExitIsolate();
958 bool retval = Dart_IsolateMakeRunnable(isolate);
959 if (!retval) {
960 *error = strdup("Invalid isolate state - Unable to make it runnable");
961 Dart_EnterIsolate(isolate);
962 Dart_ShutdownIsolate();
963 return NULL;
964 }
965
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000966 return isolate;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000967}
968
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700969#if !defined(DART_PRECOMPILED_RUNTIME)
970// Returns newly created Kernel Isolate on success, NULL on failure.
971// For now we only support the kernel isolate coming up from an
972// application snapshot or from sources which are compiled by the
973// VM parser.
974static Dart_Isolate CreateAndSetupKernelIsolate(const char* main,
975 const char* package_root,
976 const char* packages_config,
977 Dart_IsolateFlags* flags,
978 char** error,
979 int* exit_code) {
980 if (!dfe.UseDartFrontend()) {
981 *error = strdup("Kernel isolate not supported.");
982 return NULL;
983 }
984 const char* script_uri = dfe.frontend_filename();
985 if (packages_config == NULL) {
986 packages_config = commandline_packages_file;
987 }
988
989 // Kernel isolate uses an app snapshot or the core libraries snapshot.
990 bool isolate_run_app_snapshot = false;
991 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
992 const uint8_t* isolate_snapshot_instructions =
993 core_isolate_snapshot_instructions;
994 AppSnapshot* app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
995 if (app_snapshot != NULL) {
996 isolate_run_app_snapshot = true;
997 const uint8_t* ignore_vm_snapshot_data;
998 const uint8_t* ignore_vm_snapshot_instructions;
999 app_snapshot->SetBuffers(
1000 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
1001 &isolate_snapshot_data, &isolate_snapshot_instructions);
1002 }
1003
1004 IsolateData* isolate_data =
1005 new IsolateData(script_uri, package_root, packages_config, app_snapshot);
1006 Dart_Isolate isolate = Dart_CreateIsolate(
1007 script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions,
1008 flags, isolate_data, error);
1009 if (isolate == NULL) {
1010 delete isolate_data;
1011 return NULL;
1012 }
1013
Siva Annamalai53cf85a2017-07-27 10:06:52 -07001014 return IsolateSetupHelper(isolate, false, script_uri, package_root,
Siva Annamalai66564042017-06-07 13:42:17 -07001015 packages_config, isolate_snapshot_data,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001016 isolate_run_app_snapshot, error, exit_code);
1017}
1018#endif // !defined(DART_PRECOMPILED_RUNTIME)
1019
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001020// Returns newly created Service Isolate on success, NULL on failure.
1021// For now we only support the service isolate coming up from sources
1022// which are compiled by the VM parser.
1023static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
1024 const char* main,
1025 const char* package_root,
1026 const char* packages_config,
1027 Dart_IsolateFlags* flags,
1028 char** error,
1029 int* exit_code) {
1030 ASSERT(script_uri != NULL);
1031
1032#if defined(DART_PRECOMPILED_RUNTIME)
1033 // AOT: All isolates start from the app snapshot.
Siva Chandra8b405072017-06-22 10:10:42 -07001034 bool skip_library_load = true;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001035 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
1036 const uint8_t* isolate_snapshot_instructions =
1037 app_isolate_snapshot_instructions;
1038#else
1039 // JIT: Service isolate uses the core libraries snapshot.
Siva Chandra8b405072017-06-22 10:10:42 -07001040 bool skip_library_load = false;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001041 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
1042 const uint8_t* isolate_snapshot_instructions =
1043 core_isolate_snapshot_instructions;
1044#endif // !defined(DART_PRECOMPILED_RUNTIME)
1045
Siva Chandra8b405072017-06-22 10:10:42 -07001046 Dart_Isolate isolate = NULL;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001047 IsolateData* isolate_data =
1048 new IsolateData(script_uri, package_root, packages_config, NULL);
Siva Chandra8b405072017-06-22 10:10:42 -07001049#if defined(DART_PRECOMPILED_RUNTIME)
1050 isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
1051 isolate_snapshot_instructions, flags,
1052 isolate_data, error);
1053#else
1054 if (dfe.UsePlatformBinary()) {
1055 isolate = Dart_CreateIsolateFromKernel(
1056 script_uri, NULL, dfe.kernel_platform(), flags, isolate_data, error);
1057 } else {
1058 isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
1059 isolate_snapshot_instructions, flags,
1060 isolate_data, error);
1061 }
1062#endif // !defined(DART_PRECOMPILED_RUNTIME)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001063 if (isolate == NULL) {
1064 delete isolate_data;
1065 return NULL;
1066 }
1067
1068 Dart_EnterScope();
1069
1070 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
1071 CHECK_RESULT(result);
1072
Siva Chandra8b405072017-06-22 10:10:42 -07001073#if !defined(DART_PRECOMPILED_RUNTIME)
1074 if (dfe.UsePlatformBinary()) {
Alexander Markovd89b06a2017-08-16 12:44:41 -07001075 // Read vmservice_io kernel file independently of main thread
1076 // as Dart_LoadKernel takes ownership.
1077 void* kernel_vmservice_io = dfe.ReadVMServiceIO();
1078 if (kernel_vmservice_io == NULL) {
1079 Log::PrintErr("Could not read dart:vmservice_io binary file.");
1080 Platform::Exit(kErrorExitCode);
1081 }
1082 // Dart_LoadKernel takes ownership.
1083 Dart_Handle library = Dart_LoadKernel(kernel_vmservice_io);
Siva Chandra8b405072017-06-22 10:10:42 -07001084 CHECK_RESULT_CLEANUP(library, isolate_data);
1085 skip_library_load = true;
1086 }
1087#endif // !defined(DART_PRECOMPILED_RUNTIME)
1088
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001089 // Load embedder specific bits and return.
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001090 if (!VmService::Setup(vm_service_server_ip, vm_service_server_port,
1091 skip_library_load, vm_service_dev_mode,
1092 trace_loading)) {
1093 *error = strdup(VmService::GetErrorMessage());
1094 return NULL;
1095 }
1096 if (compile_all) {
1097 result = Dart_CompileAll();
1098 CHECK_RESULT(result);
1099 }
1100 result = Dart_SetEnvironmentCallback(EnvironmentCallback);
1101 CHECK_RESULT(result);
1102 Dart_ExitScope();
1103 Dart_ExitIsolate();
1104 return isolate;
1105}
1106
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001107// Returns newly created Isolate on success, NULL on failure.
1108static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
1109 const char* script_uri,
1110 const char* main,
1111 const char* package_root,
1112 const char* packages_config,
1113 Dart_IsolateFlags* flags,
1114 char** error,
1115 int* exit_code) {
1116 ASSERT(script_uri != NULL);
1117 void* kernel_platform = NULL;
1118 void* kernel_program = NULL;
1119 AppSnapshot* app_snapshot = NULL;
1120
Siva Annamalai66564042017-06-07 13:42:17 -07001121 IsolateData* isolate_data =
1122 new IsolateData(script_uri, package_root, packages_config, app_snapshot);
1123 if (is_main_isolate && (snapshot_deps_filename != NULL)) {
1124 isolate_data->set_dependencies(new MallocGrowableArray<char*>());
1125 }
1126
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001127#if defined(DART_PRECOMPILED_RUNTIME)
1128 // AOT: All isolates start from the app snapshot.
1129 bool isolate_run_app_snapshot = true;
1130 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
1131 const uint8_t* isolate_snapshot_instructions =
1132 app_isolate_snapshot_instructions;
1133#else
1134 // JIT: Main isolate starts from the app snapshot, if any. Other isolates
1135 // use the core libraries snapshot.
1136 bool isolate_run_app_snapshot = false;
1137 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
1138 const uint8_t* isolate_snapshot_instructions =
1139 core_isolate_snapshot_instructions;
1140 if ((app_isolate_snapshot_data != NULL) &&
1141 (is_main_isolate || ((app_script_uri != NULL) &&
1142 (strcmp(script_uri, app_script_uri) == 0)))) {
1143 isolate_run_app_snapshot = true;
1144 isolate_snapshot_data = app_isolate_snapshot_data;
1145 isolate_snapshot_instructions = app_isolate_snapshot_instructions;
1146 } else if (!is_main_isolate) {
1147 app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
1148 if (app_snapshot != NULL) {
1149 isolate_run_app_snapshot = true;
1150 const uint8_t* ignore_vm_snapshot_data;
1151 const uint8_t* ignore_vm_snapshot_instructions;
1152 app_snapshot->SetBuffers(
1153 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
1154 &isolate_snapshot_data, &isolate_snapshot_instructions);
1155 }
1156 }
Siva Annamalai66564042017-06-07 13:42:17 -07001157 if (!isolate_run_app_snapshot) {
1158 kernel_platform = dfe.kernel_platform();
1159 kernel_program = dfe.ReadScript(script_uri);
Siva Annamalai000bec42017-07-21 08:27:37 -07001160 if (kernel_program != NULL) {
1161 // A kernel file was specified on the command line instead of a source
1162 // file. Load that kernel file directly.
Siva Annamalai53cf85a2017-07-27 10:06:52 -07001163 dfe.set_kernel_file_specified(true);
Siva Annamalai000bec42017-07-21 08:27:37 -07001164 } else if (dfe.UseDartFrontend()) {
Siva Annamalai66564042017-06-07 13:42:17 -07001165 kernel_program = dfe.CompileAndReadScript(script_uri, error, exit_code);
1166 if (kernel_program == NULL) {
1167 return NULL;
1168 }
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001169 }
Siva Annamalai66564042017-06-07 13:42:17 -07001170 isolate_data->kernel_program = kernel_program;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001171 }
1172#endif // !defined(DART_PRECOMPILED_RUNTIME)
1173
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001174 Dart_Isolate isolate = NULL;
1175 if (kernel_platform != NULL) {
1176 isolate = Dart_CreateIsolateFromKernel(script_uri, main, kernel_platform,
1177 flags, isolate_data, error);
1178 } else if (kernel_program != NULL) {
1179 isolate = Dart_CreateIsolateFromKernel(script_uri, main, kernel_program,
1180 flags, isolate_data, error);
1181 } else {
1182 isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
1183 isolate_snapshot_instructions, flags,
1184 isolate_data, error);
1185 }
1186 if (isolate == NULL) {
1187 delete isolate_data;
1188 return NULL;
1189 }
1190
Siva Annamalai66564042017-06-07 13:42:17 -07001191 bool set_native_resolvers = (kernel_program || isolate_snapshot_data);
Siva Annamalai53cf85a2017-07-27 10:06:52 -07001192 return IsolateSetupHelper(isolate, is_main_isolate, script_uri, package_root,
1193 packages_config, set_native_resolvers,
1194 isolate_run_app_snapshot, error, exit_code);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001195}
1196
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +00001197#undef CHECK_RESULT
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001198
iposva@google.com0d0fcbe2013-04-09 17:51:24 +00001199static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
1200 const char* main,
ajohnsen@google.com0491f4e2014-09-23 05:46:14 +00001201 const char* package_root,
Ivan Posva6d066c72016-01-12 18:19:04 -08001202 const char* package_config,
Ivan Posvaf5e3f942015-06-07 17:57:34 +02001203 Dart_IsolateFlags* flags,
Zachary Anderson479a97b2016-11-04 12:30:56 -07001204 void* data,
1205 char** error) {
Ivan Posvaf5e3f942015-06-07 17:57:34 +02001206 // The VM should never call the isolate helper with a NULL flags.
1207 ASSERT(flags != NULL);
1208 ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION);
Ivan Posva6d066c72016-01-12 18:19:04 -08001209 if ((package_root != NULL) && (package_config != NULL)) {
Zachary Anderson479a97b2016-11-04 12:30:56 -07001210 *error = strdup(
1211 "Invalid arguments - Cannot simultaneously specify "
1212 "package root and package map.");
Ivan Posva60eab652015-10-12 09:05:37 -07001213 return NULL;
1214 }
Ivan Posva60eab652015-10-12 09:05:37 -07001215
1216 int exit_code = 0;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -07001217#if !defined(DART_PRECOMPILED_RUNTIME)
1218 if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
1219 return CreateAndSetupKernelIsolate(main, package_root, package_config,
1220 flags, error, &exit_code);
1221 }
1222#endif
1223 if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
1224 return CreateAndSetupServiceIsolate(script_uri, main, package_root,
1225 package_config, flags, error,
1226 &exit_code);
1227 }
1228 bool is_main_isolate = false;
Ryan Macnak26a364f2017-01-17 15:59:41 -08001229 return CreateIsolateAndSetupHelper(is_main_isolate, script_uri, main,
1230 package_root, package_config, flags, error,
1231 &exit_code);
turnidge@google.com05b5d442012-05-23 18:32:51 +00001232}
1233
iposva@google.combc268002012-10-11 07:17:09 +00001234static void PrintVersion() {
gram@google.com36019442012-11-19 17:38:15 +00001235 Log::PrintErr("Dart VM version: %s\n", Dart_VersionString());
iposva@google.combc268002012-10-11 07:17:09 +00001236}
1237
Zachary Anderson479a97b2016-11-04 12:30:56 -07001238// clang-format off
asiva@google.combde808f2011-12-20 02:04:24 +00001239static void PrintUsage() {
gram@google.com36019442012-11-19 17:38:15 +00001240 Log::PrintErr(
iposva@google.comd3f5b602012-09-24 22:26:37 +00001241 "Usage: dart [<vm-flags>] <dart-script-file> [<dart-options>]\n"
1242 "\n"
1243 "Executes the Dart script passed as <dart-script-file>.\n"
1244 "\n");
Siva Annamalai62b12f22016-02-05 15:28:59 -08001245 if (!verbose_option) {
gram@google.com36019442012-11-19 17:38:15 +00001246 Log::PrintErr(
iposva@google.comd3f5b602012-09-24 22:26:37 +00001247"Common options:\n"
asiva@google.coma12382d2013-06-10 21:57:49 +00001248"--checked or -c\n"
1249" Insert runtime type checks and enable assertions (checked mode).\n"
1250"--help or -h\n"
1251" Display this message (add -v or --verbose for information about\n"
1252" all VM options).\n"
1253"--package-root=<path> or -p<path>\n"
1254" Where to find packages, that is, \"package:...\" imports.\n"
Ivan Posvab07a9dd2015-07-29 11:30:33 -07001255"--packages=<path>\n"
1256" Where to find a package spec file.\n"
Ryan Macnakba884352015-08-04 15:14:48 -07001257"--observe[=<port>[/<bind-address>]]\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001258" The observe flag is a convenience flag used to run a program with a\n"
1259" set of options which are often useful for debugging under Observatory.\n"
Todd Turnidgea02995c2016-05-13 11:07:15 -07001260" These options are currently:\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001261" --enable-vm-service[=<port>[/<bind-address>]]\n"
1262" --pause-isolates-on-exit\n"
1263" --pause-isolates-on-unhandled-exceptions\n"
1264" --warn-on-pause-with-no-debugger\n"
Todd Turnidgea02995c2016-05-13 11:07:15 -07001265" This set is subject to change.\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001266" Please see these options (--help --verbose) for further documentation.\n"
kdakere3536552017-02-18 17:06:51 -08001267"--snapshot-kind=<snapshot_kind>\n"
Siva Annamalai9c737d62016-10-20 13:54:35 -07001268"--snapshot=<file_name>\n"
1269" These snapshot options are used to generate a snapshot of the loaded\n"
1270" Dart script:\n"
1271" <snapshot-kind> controls the kind of snapshot, it could be\n"
1272" script(default), app-aot or app-jit\n"
1273" <file_name> specifies the file into which the snapshot is written\n"
asiva@google.coma12382d2013-06-10 21:57:49 +00001274"--version\n"
1275" Print the VM version.\n");
iposva@google.comd3f5b602012-09-24 22:26:37 +00001276 } else {
gram@google.com36019442012-11-19 17:38:15 +00001277 Log::PrintErr(
iposva@google.comd3f5b602012-09-24 22:26:37 +00001278"Supported options:\n"
asiva@google.coma12382d2013-06-10 21:57:49 +00001279"--checked or -c\n"
iposva@google.comd3f5b602012-09-24 22:26:37 +00001280" Insert runtime type checks and enable assertions (checked mode).\n"
asiva@google.coma12382d2013-06-10 21:57:49 +00001281"--help or -h\n"
1282" Display this message (add -v or --verbose for information about\n"
1283" all VM options).\n"
1284"--package-root=<path> or -p<path>\n"
1285" Where to find packages, that is, \"package:...\" imports.\n"
Ryan Macnakba884352015-08-04 15:14:48 -07001286"--packages=<path>\n"
1287" Where to find a package spec file.\n"
1288"--observe[=<port>[/<bind-address>]]\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001289" The observe flag is a convenience flag used to run a program with a\n"
1290" set of options which are often useful for debugging under Observatory.\n"
Todd Turnidgea02995c2016-05-13 11:07:15 -07001291" These options are currently:\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001292" --enable-vm-service[=<port>[/<bind-address>]]\n"
1293" --pause-isolates-on-exit\n"
1294" --pause-isolates-on-unhandled-exceptions\n"
1295" --warn-on-pause-with-no-debugger\n"
Todd Turnidgea02995c2016-05-13 11:07:15 -07001296" This set is subject to change.\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001297" Please see these options for further documentation.\n"
kdakere3536552017-02-18 17:06:51 -08001298"--snapshot-kind=<snapshot_kind>\n"
Siva Annamalai9c737d62016-10-20 13:54:35 -07001299"--snapshot=<file_name>\n"
1300" These snapshot options are used to generate a snapshot of the loaded\n"
1301" Dart script:\n"
1302" <snapshot-kind> controls the kind of snapshot, it could be\n"
1303" script(default), app-aot or app-jit\n"
1304" <file_name> specifies the file into which the snapshot is written\n"
iposva@google.combc268002012-10-11 07:17:09 +00001305"--version\n"
1306" Print the VM version.\n"
1307"\n"
iposva@google.comd0763f92015-05-11 22:58:32 +00001308"--trace-loading\n"
1309" enables tracing of library and script loading\n"
asiva@google.com6b8987e2013-03-14 09:47:46 +00001310"\n"
Todd Turnidgebd3cdf42016-05-13 10:51:51 -07001311"--enable-vm-service[=<port>[/<bind-address>]]\n"
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +00001312" enables the VM service and listens on specified port for connections\n"
Ryan Macnak1b518892016-11-23 14:24:52 -08001313" (default port number is 8181, default bind address is localhost).\n"
Ryan Macnak87728492017-03-15 13:11:05 -07001314#if !defined(HOST_OS_MACOS)
Zachary Anderson139db222016-09-16 09:08:51 -07001315"\n"
1316"--root-certs-file=<path>\n"
1317" The path to a file containing the trusted root certificates to use for\n"
1318" secure socket connections.\n"
1319"--root-certs-cache=<path>\n"
1320" The path to a cache directory containing the trusted root certificates to\n"
1321" use for secure socket connections.\n"
Ryan Macnak87728492017-03-15 13:11:05 -07001322#endif // !defined(HOST_OS_MACOS)
iposva@google.comd0763f92015-05-11 22:58:32 +00001323"\n"
iposva@google.comd3f5b602012-09-24 22:26:37 +00001324"The following options are only used for VM development and may\n"
1325"be changed in any future version:\n");
1326 const char* print_flags = "--print_flags";
1327 Dart_SetVMFlags(1, &print_flags);
1328 }
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001329}
Zachary Anderson479a97b2016-11-04 12:30:56 -07001330// clang-format on
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001331
Zachary Anderson479a97b2016-11-04 12:30:56 -07001332char* BuildIsolateName(const char* script_name, const char* func_name) {
turnidge@google.come62f34c2012-01-18 21:46:27 +00001333 // Skip past any slashes in the script name.
1334 const char* last_slash = strrchr(script_name, '/');
1335 if (last_slash != NULL) {
1336 script_name = last_slash + 1;
1337 }
1338
1339 const char* kFormat = "%s/%s";
1340 intptr_t len = strlen(script_name) + strlen(func_name) + 2;
1341 char* buffer = new char[len];
1342 ASSERT(buffer != NULL);
1343 snprintf(buffer, len, kFormat, script_name, func_name);
1344 return buffer;
1345}
1346
Vyacheslav Egorova5e1f892017-02-28 21:10:04 +01001347static void OnIsolateShutdown(void* callback_data) {
1348 IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
1349 isolate_data->OnIsolateShutdown();
1350}
1351
Vyacheslav Egorova5e1f892017-02-28 21:10:04 +01001352static void DeleteIsolateData(void* callback_data) {
ager@google.comf791a122012-06-29 14:40:17 +00001353 IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
ager@google.comf791a122012-06-29 14:40:17 +00001354 delete isolate_data;
1355}
1356
Todd Turnidgee4684c72015-07-14 12:54:07 -07001357static const char* kStdoutStreamId = "Stdout";
1358static const char* kStderrStreamId = "Stderr";
1359
Todd Turnidgee4684c72015-07-14 12:54:07 -07001360static bool ServiceStreamListenCallback(const char* stream_id) {
1361 if (strcmp(stream_id, kStdoutStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -08001362 SetCaptureStdout(true);
Todd Turnidgee4684c72015-07-14 12:54:07 -07001363 return true;
1364 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -08001365 SetCaptureStderr(true);
Todd Turnidgee4684c72015-07-14 12:54:07 -07001366 return true;
1367 }
1368 return false;
1369}
1370
Todd Turnidgee4684c72015-07-14 12:54:07 -07001371static void ServiceStreamCancelCallback(const char* stream_id) {
1372 if (strcmp(stream_id, kStdoutStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -08001373 SetCaptureStdout(false);
Todd Turnidgee4684c72015-07-14 12:54:07 -07001374 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -08001375 SetCaptureStderr(false);
Todd Turnidgee4684c72015-07-14 12:54:07 -07001376 }
Todd Turnidgee4684c72015-07-14 12:54:07 -07001377}
1378
Todd Turnidge1166f832016-07-29 11:23:18 -07001379static bool FileModifiedCallback(const char* url, int64_t since) {
1380 if (strncmp(url, "file:///", 8) == 0) {
1381 // If it isn't a file on local disk, we don't know if it has been
1382 // modified.
1383 return true;
1384 }
1385 int64_t data[File::kStatSize];
1386 File::Stat(url + 7, data);
1387 if (data[File::kType] == File::kDoesNotExist) {
1388 return true;
1389 }
1390 bool modified = data[File::kModifiedTime] > since;
1391 return modified;
1392}
1393
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -07001394static void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -07001395 info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
1396 info->name = "Dart VM";
Carlo Bernaschina491390e2017-08-16 10:59:20 -07001397 Process::GetRSSInformation(&(info->max_rss), &(info->current_rss));
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -07001398}
1399
Ryan Macnakb46af1e2017-01-23 10:25:02 -08001400static void GenerateAppAOTSnapshot() {
Ryan Macnak257b3a82016-05-04 18:47:36 -07001401 if (use_blobs) {
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001402 Snapshot::GenerateAppAOTAsBlobs(snapshot_filename);
Ryan Macnak257b3a82016-05-04 18:47:36 -07001403 } else {
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001404 Snapshot::GenerateAppAOTAsAssembly(snapshot_filename);
Ryan Macnak257b3a82016-05-04 18:47:36 -07001405 }
1406}
1407
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001408#define CHECK_RESULT(result) \
1409 if (Dart_IsError(result)) { \
Zachary Anderson479a97b2016-11-04 12:30:56 -07001410 const int exit_code = Dart_IsCompilationError(result) \
1411 ? kCompilationErrorExitCode \
1412 : kErrorExitCode; \
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001413 ErrorExit(exit_code, "%s\n", Dart_GetError(result)); \
1414 }
1415
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001416static void WriteFile(const char* filename,
1417 const uint8_t* buffer,
1418 const intptr_t size) {
1419 File* file = File::Open(filename, File::kWriteTruncate);
1420 if (file == NULL) {
1421 ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename);
Ryan Macnak4d65db8a2016-10-31 15:56:25 -07001422 }
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001423 if (!file->WriteFully(buffer, size)) {
1424 ErrorExit(kErrorExitCode, "Unable to write file %s\n", filename);
Ryan Macnak5ee94eb2016-10-19 09:37:47 -07001425 }
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001426 file->Release();
Ryan Macnak5ee94eb2016-10-19 09:37:47 -07001427}
1428
Ryan Macnak74f3d1b2017-06-05 16:56:16 -07001429static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) {
1430 File* file = File::Open(filename, File::kRead);
1431 if (file == NULL) {
1432 ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename);
1433 }
1434 *size = file->Length();
1435 *buffer = reinterpret_cast<uint8_t*>(malloc(*size));
1436 if (!file->ReadFully(*buffer, *size)) {
1437 ErrorExit(kErrorExitCode, "Unable to read file %s\n", filename);
1438 }
1439 file->Release();
1440}
1441
Vyacheslav Egorov7d523172017-08-25 09:48:20 +02001442static Dart_QualifiedFunctionName standalone_entry_points[] = {
1443 // Functions.
1444 {"dart:_builtin", "::", "_getPrintClosure"},
1445 {"dart:_builtin", "::", "_libraryFilePath"},
1446 {"dart:_builtin", "::", "_resolveInWorkingDirectory"},
1447 {"dart:_builtin", "::", "_setPackageRoot"},
1448 {"dart:_builtin", "::", "_setPackagesMap"},
1449 {"dart:_builtin", "::", "_setWorkingDirectory"},
1450 {"dart:async", "::", "_setScheduleImmediateClosure"},
1451 {"dart:io", "::", "_getWatchSignalInternal"},
1452 {"dart:io", "::", "_getUriBaseClosure"},
1453 {"dart:io", "::", "_makeDatagram"},
1454 {"dart:io", "::", "_makeUint8ListView"},
1455 {"dart:io", "::", "_setupHooks"},
1456 {"dart:io", "CertificateException", "CertificateException."},
1457 {"dart:io", "Directory", "Directory."},
1458 {"dart:io", "File", "File."},
1459 {"dart:io", "FileSystemException", "FileSystemException."},
1460 {"dart:io", "HandshakeException", "HandshakeException."},
1461 {"dart:io", "Link", "Link."},
1462 {"dart:io", "OSError", "OSError."},
1463 {"dart:io", "TlsException", "TlsException."},
1464 {"dart:io", "X509Certificate", "X509Certificate._"},
1465 {"dart:io", "_ExternalBuffer", "get:end"},
1466 {"dart:io", "_ExternalBuffer", "get:start"},
1467 {"dart:io", "_ExternalBuffer", "set:data"},
1468 {"dart:io", "_ExternalBuffer", "set:end"},
1469 {"dart:io", "_ExternalBuffer", "set:start"},
1470 {"dart:io", "_Platform", "set:_nativeScript"},
1471 {"dart:io", "_ProcessStartStatus", "set:_errorCode"},
1472 {"dart:io", "_ProcessStartStatus", "set:_errorMessage"},
1473 {"dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE"},
1474 {"dart:io", "_SecureFilterImpl", "get:SIZE"},
1475 {"dart:io", "_SecureFilterImpl", "get:buffers"},
1476 {"dart:isolate", "::", "_getIsolateScheduleImmediateClosure"},
1477 {"dart:isolate", "::", "_setupHooks"},
1478 {"dart:isolate", "::", "_startMainIsolate"},
1479 {"dart:vmservice_io", "::", "main"},
1480 // Fields
1481 {"dart:_builtin", "::", "_isolateId"},
1482 {"dart:_builtin", "::", "_loadPort"},
1483 {"dart:_internal", "::", "_printClosure"},
1484 {"dart:vmservice_io", "::", "_autoStart"},
1485 {"dart:vmservice_io", "::", "_ip"},
1486 {"dart:vmservice_io", "::", "_isFuchsia"},
1487 {"dart:vmservice_io", "::", "_isWindows"},
1488 {"dart:vmservice_io", "::", "_originCheckDisabled"},
1489 {"dart:vmservice_io", "::", "_port"},
1490 {"dart:vmservice_io", "::", "_signalWatch"},
1491 {"dart:vmservice_io", "::", "_traceLoading"},
1492 {NULL, NULL, NULL} // Must be terminated with NULL entries.
1493};
1494
Zachary Anderson479a97b2016-11-04 12:30:56 -07001495bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001496 // Call CreateIsolateAndSetup which creates an isolate and loads up
1497 // the specified application script.
1498 char* error = NULL;
Ryan Macnak26a364f2017-01-17 15:59:41 -08001499 bool is_main_isolate = true;
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001500 int exit_code = 0;
1501 char* isolate_name = BuildIsolateName(script_name, "main");
Vyacheslav Egorov7d523172017-08-25 09:48:20 +02001502 Dart_IsolateFlags flags;
1503 Dart_IsolateFlagsInitialize(&flags);
1504
1505 if (gen_snapshot_kind == kAppAOT) {
1506 flags.obfuscate = obfuscate;
1507 flags.entry_points = standalone_entry_points;
1508 }
1509
Zachary Anderson479a97b2016-11-04 12:30:56 -07001510 Dart_Isolate isolate = CreateIsolateAndSetupHelper(
Ryan Macnak26a364f2017-01-17 15:59:41 -08001511 is_main_isolate, script_name, "main", commandline_package_root,
Vyacheslav Egorov7d523172017-08-25 09:48:20 +02001512 commandline_packages_file, &flags, &error, &exit_code);
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001513 if (isolate == NULL) {
Zachary Anderson479a97b2016-11-04 12:30:56 -07001514 delete[] isolate_name;
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001515 Log::PrintErr("%s\n", error);
1516 free(error);
1517 error = NULL;
1518 Process::TerminateExitCodeHandler();
1519 error = Dart_Cleanup();
1520 if (error != NULL) {
1521 Log::PrintErr("VM cleanup failed: %s\n", error);
1522 free(error);
1523 }
Zachary Anderson89dba572017-03-28 07:44:04 -07001524 Process::ClearAllSignalHandlers();
Florian Schneider63e3f4d2016-07-13 09:41:06 -07001525 EventHandler::Stop();
Zachary Anderson3563dc02015-10-29 23:35:46 -07001526 Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001527 }
Ryan Macnak4d65db8a2016-10-31 15:56:25 -07001528 main_isolate = isolate;
Zachary Anderson479a97b2016-11-04 12:30:56 -07001529 delete[] isolate_name;
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001530
1531 Dart_EnterIsolate(isolate);
1532 ASSERT(isolate == Dart_CurrentIsolate());
1533 ASSERT(isolate != NULL);
1534 Dart_Handle result;
1535
1536 Dart_EnterScope();
1537
Ryan Macnak7546ef12016-05-06 12:40:04 -07001538 if (gen_snapshot_kind == kScript) {
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001539 Snapshot::GenerateScript(snapshot_filename);
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001540 } else {
1541 // Lookup the library of the root script.
1542 Dart_Handle root_lib = Dart_RootLibrary();
1543 // Import the root library into the builtin library so that we can easily
1544 // lookup the main entry point exported from the root library.
Siva Annamalai1e5eab32016-02-04 09:18:31 -08001545 IsolateData* isolate_data =
1546 reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
Zachary Anderson479a97b2016-11-04 12:30:56 -07001547 result = Dart_LibraryImportLibrary(isolate_data->builtin_lib(), root_lib,
1548 Dart_Null());
Florian Schneiderbef49672017-01-11 16:55:55 -08001549 if ((gen_snapshot_kind == kAppAOT) || (gen_snapshot_kind == kAppJIT)) {
Alexander Markovd89b06a2017-08-16 12:44:41 -07001550 // Load the embedder's portion of the VM service's Dart code so it will
1551 // be included in the app snapshot.
1552 void* kernel_vmservice_io = NULL;
1553#if !defined(DART_PRECOMPILED_RUNTIME)
1554 if (dfe.UsePlatformBinary()) {
1555 // Do not cache vmservice_io kernel file as
1556 // VmService::LoadForGenPrecompiled takes ownership.
1557 kernel_vmservice_io = dfe.ReadVMServiceIO();
1558 if (kernel_vmservice_io == NULL) {
1559 Log::PrintErr("Could not read dart:vmservice_io binary file.");
1560 Platform::Exit(kErrorExitCode);
1561 }
1562 }
Siva Chandraa23178e2017-06-23 09:39:15 -07001563#endif // defined(DART_PRECOMPILED_RUNTIME)
Alexander Markovd89b06a2017-08-16 12:44:41 -07001564 if (!VmService::LoadForGenPrecompiled(kernel_vmservice_io)) {
Ryan Macnak5ee71ca2016-11-22 09:59:06 -08001565 Log::PrintErr("VM service loading failed: %s\n",
1566 VmService::GetErrorMessage());
Alexander Markovd89b06a2017-08-16 12:44:41 -07001567 Platform::Exit(kErrorExitCode);
Ryan Macnak37dd8762015-10-29 15:15:46 -07001568 }
1569 }
1570
Siva Annamalai62b12f22016-02-05 15:28:59 -08001571 if (compile_all) {
Ryan Macnak9328d722016-01-08 10:19:14 -08001572 result = Dart_CompileAll();
1573 CHECK_RESULT(result);
1574 }
1575
Siva Annamalai12f86592016-09-23 15:20:39 -07001576 if (parse_all) {
1577 result = Dart_ParseAll();
1578 CHECK_RESULT(result);
1579 Dart_ExitScope();
1580 // Shutdown the isolate.
1581 Dart_ShutdownIsolate();
1582 return false;
1583 }
1584
Florian Schneiderbef49672017-01-11 16:55:55 -08001585 if (gen_snapshot_kind == kAppAOT) {
Ryan Macnak4607e382016-12-16 16:00:17 -08001586 uint8_t* feedback_buffer = NULL;
1587 intptr_t feedback_length = 0;
1588 if (load_feedback_filename != NULL) {
1589 File* file = File::Open(load_feedback_filename, File::kRead);
1590 if (file == NULL) {
1591 ErrorExit(kErrorExitCode, "Failed to read JIT feedback.\n");
1592 }
1593 feedback_length = file->Length();
1594 feedback_buffer = reinterpret_cast<uint8_t*>(malloc(feedback_length));
1595 if (!file->ReadFully(feedback_buffer, feedback_length)) {
1596 ErrorExit(kErrorExitCode, "Failed to read JIT feedback.\n");
1597 }
1598 file->Release();
1599 }
1600
Florian Schneiderbef49672017-01-11 16:55:55 -08001601 result = Dart_Precompile(standalone_entry_points, feedback_buffer,
1602 feedback_length);
Ryan Macnak4607e382016-12-16 16:00:17 -08001603 if (feedback_buffer != NULL) {
1604 free(feedback_buffer);
1605 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001606 CHECK_RESULT(result);
Vyacheslav Egorov7d523172017-08-25 09:48:20 +02001607
1608 if (obfuscate && obfuscation_map_filename != NULL) {
1609 uint8_t* buffer = NULL;
1610 intptr_t size = 0;
1611 result = Dart_GetObfuscationMap(&buffer, &size);
1612 CHECK_RESULT(result);
1613 WriteFile(obfuscation_map_filename, buffer, size);
1614 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001615 }
1616
Ryan Macnak7546ef12016-05-06 12:40:04 -07001617 if (gen_snapshot_kind == kAppAOT) {
Ryan Macnakb46af1e2017-01-23 10:25:02 -08001618 GenerateAppAOTSnapshot();
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001619 } else {
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001620 if (Dart_IsNull(root_lib)) {
Zachary Anderson479a97b2016-11-04 12:30:56 -07001621 ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001622 script_name);
1623 }
1624
Ryan Macnak74f3d1b2017-06-05 16:56:16 -07001625 if (gen_snapshot_kind == kAppJIT) {
1626 result = Dart_SortClasses();
1627 CHECK_RESULT(result);
1628 }
1629
1630 if (load_compilation_trace_filename != NULL) {
1631 uint8_t* buffer = NULL;
1632 intptr_t size = 0;
1633 ReadFile(load_compilation_trace_filename, &buffer, &size);
1634 result = Dart_LoadCompilationTrace(buffer, size);
1635 CHECK_RESULT(result);
1636 }
Erik Corryc6a199e2017-02-20 12:14:17 +01001637
Siva Annamalai8b7af732017-06-15 10:40:43 -07001638 // Create a closure for the main entry point which is in the exported
1639 // namespace of the root library or invoke a getter of the same name
1640 // in the exported namespace and return the resulting closure.
Zachary Anderson479a97b2016-11-04 12:30:56 -07001641 Dart_Handle main_closure =
Siva Annamalai8b7af732017-06-15 10:40:43 -07001642 Dart_GetClosure(root_lib, Dart_NewStringFromCString("main"));
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001643 CHECK_RESULT(main_closure);
Siva Annamalai8b7af732017-06-15 10:40:43 -07001644 if (!Dart_IsClosure(main_closure)) {
1645 ErrorExit(kErrorExitCode,
1646 "Unable to find 'main' in root library '%s'\n", script_name);
1647 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001648
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001649 // Call _startIsolate in the isolate library to enable dispatching the
1650 // initial startup message.
1651 const intptr_t kNumIsolateArgs = 2;
1652 Dart_Handle isolate_args[kNumIsolateArgs];
1653 isolate_args[0] = main_closure; // entryPoint
1654 isolate_args[1] = CreateRuntimeOptions(dart_options); // args
1655
1656 Dart_Handle isolate_lib =
1657 Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
1658 result = Dart_Invoke(isolate_lib,
1659 Dart_NewStringFromCString("_startMainIsolate"),
1660 kNumIsolateArgs, isolate_args);
1661 CHECK_RESULT(result);
1662
1663 // Keep handling messages until the last active receive port is closed.
1664 result = Dart_RunLoop();
Ryan Macnak7546ef12016-05-06 12:40:04 -07001665 // Generate an app snapshot after execution if specified.
Siva Annamalai36a237c2016-10-19 17:48:01 -07001666 if (gen_snapshot_kind == kAppJIT) {
John McCutchana4adbffb2017-03-20 08:47:39 -07001667 if (!Dart_IsCompilationError(result)) {
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001668 Snapshot::GenerateAppJIT(snapshot_filename);
Siva Annamalai4f24d172016-02-12 10:48:43 -08001669 }
Siva Annamalai040637a2015-10-16 17:10:30 -07001670 }
Siva Annamalai4f24d172016-02-12 10:48:43 -08001671 CHECK_RESULT(result);
Ryan Macnak4607e382016-12-16 16:00:17 -08001672
1673 if (save_feedback_filename != NULL) {
1674 uint8_t* buffer = NULL;
1675 intptr_t size = 0;
1676 result = Dart_SaveJITFeedback(&buffer, &size);
Ryan Macnak74f3d1b2017-06-05 16:56:16 -07001677 CHECK_RESULT(result);
Ryan Macnak6500f6e2017-02-13 11:17:31 -08001678 WriteFile(save_feedback_filename, buffer, size);
Ryan Macnak4607e382016-12-16 16:00:17 -08001679 }
Ryan Macnak74f3d1b2017-06-05 16:56:16 -07001680
1681 if (save_compilation_trace_filename != NULL) {
1682 uint8_t* buffer = NULL;
1683 intptr_t size = 0;
1684 result = Dart_SaveCompilationTrace(&buffer, &size);
1685 CHECK_RESULT(result);
1686 WriteFile(save_compilation_trace_filename, buffer, size);
1687 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001688 }
1689 }
1690
P.Y. Laligand8f035202017-03-27 06:44:21 -07001691 if (snapshot_deps_filename != NULL) {
Ryan Macnak06080da2017-04-26 15:34:29 -07001692 Loader::ResolveDependenciesAsFilePaths();
P.Y. Laligand8f035202017-03-27 06:44:21 -07001693 IsolateData* isolate_data =
1694 reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
1695 ASSERT(isolate_data != NULL);
1696 MallocGrowableArray<char*>* dependencies = isolate_data->dependencies();
1697 ASSERT(dependencies != NULL);
1698 File* file = File::Open(snapshot_deps_filename, File::kWriteTruncate);
1699 if (file == NULL) {
1700 ErrorExit(kErrorExitCode,
1701 "Error: Unable to open snapshot depfile: %s\n\n",
1702 snapshot_deps_filename);
1703 }
1704 bool success = true;
1705 success &= file->Print("%s: ", snapshot_filename);
1706 for (intptr_t i = 0; i < dependencies->length(); i++) {
1707 char* dep = dependencies->At(i);
1708 success &= file->Print("%s ", dep);
1709 free(dep);
1710 }
1711 success &= file->Print("\n");
1712 if (!success) {
1713 ErrorExit(kErrorExitCode,
1714 "Error: Unable to write snapshot depfile: %s\n\n",
1715 snapshot_deps_filename);
1716 }
1717 file->Release();
1718 isolate_data->set_dependencies(NULL);
1719 delete dependencies;
1720 }
1721
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001722 Dart_ExitScope();
P.Y. Laligand8f035202017-03-27 06:44:21 -07001723
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001724 // Shutdown the isolate.
1725 Dart_ShutdownIsolate();
1726
1727 // No restart.
1728 return false;
1729}
1730
1731#undef CHECK_RESULT
1732
Ivan Posva9535aa62016-03-04 16:05:54 -08001733// Observatory assets are only needed in the regular dart binary.
Zachary Andersonb0503ad2016-07-22 14:07:07 -07001734#if !defined(DART_PRECOMPILER) && !defined(NO_OBSERVATORY)
John McCutchan2844eb82015-10-26 07:21:23 -07001735extern unsigned int observatory_assets_archive_len;
John McCutchan33814bd2015-10-27 08:56:02 -07001736extern const uint8_t* observatory_assets_archive;
John McCutchan2844eb82015-10-26 07:21:23 -07001737
John McCutchancc0f2972015-12-16 12:35:58 -08001738
John McCutchan2844eb82015-10-26 07:21:23 -07001739Dart_Handle GetVMServiceAssetsArchiveCallback() {
John McCutchancc0f2972015-12-16 12:35:58 -08001740 uint8_t* decompressed = NULL;
Ryan Macnak7dfe62f2017-08-11 12:18:16 -07001741 intptr_t decompressed_len = 0;
Zachary Anderson479a97b2016-11-04 12:30:56 -07001742 Decompress(observatory_assets_archive, observatory_assets_archive_len,
1743 &decompressed, &decompressed_len);
1744 Dart_Handle tar_file =
1745 DartUtils::MakeUint8Array(decompressed, decompressed_len);
John McCutchancc0f2972015-12-16 12:35:58 -08001746 // Free decompressed memory as it has been copied into a Dart array.
1747 free(decompressed);
1748 return tar_file;
John McCutchan2844eb82015-10-26 07:21:23 -07001749}
Zachary Anderson479a97b2016-11-04 12:30:56 -07001750#else // !defined(DART_PRECOMPILER)
Ivan Posva9535aa62016-03-04 16:05:54 -08001751static Dart_GetVMServiceAssetsArchive GetVMServiceAssetsArchiveCallback = NULL;
1752#endif // !defined(DART_PRECOMPILER)
John McCutchan2844eb82015-10-26 07:21:23 -07001753
johnmccutchan@google.coma80d3282013-11-26 18:13:51 +00001754void main(int argc, char** argv) {
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001755 char* script_name;
John McCutchan24a09882016-07-11 13:58:26 -07001756 const int EXTRA_VM_ARGUMENTS = 8;
Srdjan Mitrovicfc3cd692015-05-27 17:11:35 -07001757 CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001758 CommandLineOptions dart_options(argc);
asiva@google.comc7f58ad2012-06-13 17:48:47 +00001759 bool print_flags_seen = false;
tball@google.comb3cae062013-04-05 20:55:10 +00001760 bool verbose_debug_seen = false;
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001761
sgjesse@google.comd7c8c1f2011-11-23 14:49:18 +00001762 // Perform platform specific initialization.
1763 if (!Platform::Initialize()) {
gram@google.com36019442012-11-19 17:38:15 +00001764 Log::PrintErr("Initialization failed\n");
sgjesse@google.comd7c8c1f2011-11-23 14:49:18 +00001765 }
1766
ager@google.com28b43142012-11-13 15:03:23 +00001767 // On Windows, the argv strings are code page encoded and not
1768 // utf8. We need to convert them to utf8.
Soren Gjesse0415d922015-06-24 10:36:05 +02001769 bool argv_converted = ShellUtils::GetUtf8Argv(argc, argv);
ager@google.com28b43142012-11-13 15:03:23 +00001770
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001771 // Parse command line arguments.
Zachary Anderson479a97b2016-11-04 12:30:56 -07001772 if (ParseArguments(argc, argv, &vm_options, &script_name, &dart_options,
1773 &print_flags_seen, &verbose_debug_seen) < 0) {
Siva Annamalai62b12f22016-02-05 15:28:59 -08001774 if (help_option) {
iposva@google.combc268002012-10-11 07:17:09 +00001775 PrintUsage();
Zachary Anderson3563dc02015-10-29 23:35:46 -07001776 Platform::Exit(0);
Siva Annamalai62b12f22016-02-05 15:28:59 -08001777 } else if (version_option) {
iposva@google.combc268002012-10-11 07:17:09 +00001778 PrintVersion();
Zachary Anderson3563dc02015-10-29 23:35:46 -07001779 Platform::Exit(0);
iposva@google.combc268002012-10-11 07:17:09 +00001780 } else if (print_flags_seen) {
asiva@google.comc7f58ad2012-06-13 17:48:47 +00001781 // Will set the VM flags, print them out and then we exit as no
1782 // script was specified on the command line.
1783 Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
Zachary Anderson3563dc02015-10-29 23:35:46 -07001784 Platform::Exit(0);
asiva@google.comc7f58ad2012-06-13 17:48:47 +00001785 } else {
1786 PrintUsage();
Zachary Anderson3563dc02015-10-29 23:35:46 -07001787 Platform::Exit(kErrorExitCode);
asiva@google.comc7f58ad2012-06-13 17:48:47 +00001788 }
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001789 }
1790
iposva@google.come57e60c2014-08-14 05:00:37 +00001791 Thread::InitOnce();
1792
Florian Schneider63e3f4d2016-07-13 09:41:06 -07001793 Loader::InitOnce();
1794
iposva@google.com35a8e252013-09-13 16:40:36 +00001795 if (!DartUtils::SetOriginalWorkingDirectory()) {
1796 OSError err;
Ryan Macnak5ee71ca2016-11-22 09:59:06 -08001797 Log::PrintErr("Error determining current directory: %s\n", err.message());
Zachary Anderson3563dc02015-10-29 23:35:46 -07001798 Platform::Exit(kErrorExitCode);
iposva@google.com35a8e252013-09-13 16:40:36 +00001799 }
1800
Siva Annamalai7aed6c02017-05-19 13:41:21 -07001801 AppSnapshot* app_snapshot = Snapshot::TryReadAppSnapshot(script_name);
Ryan Macnaka317b902017-02-16 13:54:57 -08001802 if (app_snapshot != NULL) {
Ryan Macnak26a364f2017-01-17 15:59:41 -08001803 vm_run_app_snapshot = true;
Ryan Macnaka317b902017-02-16 13:54:57 -08001804 app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
1805 &app_isolate_snapshot_data,
1806 &app_isolate_snapshot_instructions);
Ryan Macnak3d00ecd2016-10-14 09:57:54 -07001807 }
1808
Ryan Macnak7546ef12016-05-06 12:40:04 -07001809#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
1810 // Constant true if PRODUCT or DART_PRECOMPILED_RUNTIME.
Ryan Macnak26a364f2017-01-17 15:59:41 -08001811 if ((gen_snapshot_kind != kNone) || vm_run_app_snapshot) {
Srdjan Mitrovicfc3cd692015-05-27 17:11:35 -07001812 vm_options.AddArgument("--load_deferred_eagerly");
1813 }
Florian Schneiderd8677962016-02-25 07:53:39 -08001814#endif
Srdjan Mitrovicfc3cd692015-05-27 17:11:35 -07001815
Siva Annamalaiaf4d2462016-10-19 17:42:01 -07001816 if (gen_snapshot_kind == kAppJIT) {
Ryan Macnakad32e932016-10-07 10:34:57 -07001817 vm_options.AddArgument("--fields_may_be_reset");
Ryan Macnakf555cf82016-11-16 10:02:02 -08001818#if !defined(PRODUCT)
Ryan Macnak13ba4b22016-11-16 09:10:22 -08001819 vm_options.AddArgument("--collect_code=false");
Ryan Macnakf555cf82016-11-16 10:02:02 -08001820#endif
Ryan Macnakad32e932016-10-07 10:34:57 -07001821 }
Florian Schneiderbef49672017-01-11 16:55:55 -08001822 if (gen_snapshot_kind == kAppAOT) {
Ryan Macnak7546ef12016-05-06 12:40:04 -07001823 vm_options.AddArgument("--precompilation");
1824 }
1825#if defined(DART_PRECOMPILED_RUNTIME)
Florian Schneider23dd0b92016-02-04 16:33:37 -08001826 vm_options.AddArgument("--precompilation");
Florian Schneider0f486902016-02-02 17:51:15 -08001827#endif
Ryan Macnak4d65db8a2016-10-31 15:56:25 -07001828 if (gen_snapshot_kind == kAppJIT) {
1829 Process::SetExitHook(SnapshotOnExitHook);
1830 }
Florian Schneider0f486902016-02-02 17:51:15 -08001831
Siva Chandra8b405072017-06-22 10:10:42 -07001832#if !defined(DART_PRECOMPILED_RUNTIME)
1833 // If a kernel platform binary file is specified, read it. This
1834 // step will become redundant once we have the snapshot version
1835 // of the kernel core/platform libraries.
1836 if (dfe.UsePlatformBinary()) {
Alexander Markovd89b06a2017-08-16 12:44:41 -07001837 void* kernel_platform = dfe.ReadPlatform();
1838 if (kernel_platform == NULL) {
Siva Chandra8b405072017-06-22 10:10:42 -07001839 Log::PrintErr("The platform binary is not a valid Dart Kernel file.");
1840 Platform::Exit(kErrorExitCode);
1841 }
Alexander Markovd89b06a2017-08-16 12:44:41 -07001842 dfe.set_kernel_platform(kernel_platform);
Siva Chandra8b405072017-06-22 10:10:42 -07001843 }
1844#endif
1845
podivilov@google.comc6926462011-12-01 11:59:35 +00001846 Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
1847
johnmccutchan@google.com172baa02015-01-29 18:31:27 +00001848 // Start event handler.
Ryan Macnak22683802015-12-18 13:20:57 -08001849 TimerUtils::InitOnce();
johnmccutchan@google.com172baa02015-01-29 18:31:27 +00001850 EventHandler::Start();
1851
johnmccutchan@google.com9b1f39b2015-02-12 21:22:34 +00001852 // Initialize the Dart VM.
Adam Barthfac99f32016-08-09 12:25:29 -07001853 Dart_InitializeParams init_params;
1854 memset(&init_params, 0, sizeof(init_params));
1855 init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
Ryan Macnakb46af1e2017-01-23 10:25:02 -08001856 init_params.vm_snapshot_data = vm_snapshot_data;
1857 init_params.vm_snapshot_instructions = vm_snapshot_instructions;
Adam Barthfac99f32016-08-09 12:25:29 -07001858 init_params.create = CreateIsolateAndSetup;
Vyacheslav Egorova5e1f892017-02-28 21:10:04 +01001859 init_params.shutdown = OnIsolateShutdown;
1860 init_params.cleanup = DeleteIsolateData;
Adam Barthfac99f32016-08-09 12:25:29 -07001861 init_params.file_open = DartUtils::OpenFile;
1862 init_params.file_read = DartUtils::ReadFile;
1863 init_params.file_write = DartUtils::WriteFile;
1864 init_params.file_close = DartUtils::CloseFile;
1865 init_params.entropy_source = DartUtils::EntropySource;
1866 init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
Siva Annamalai73d30072017-08-11 12:38:22 -07001867#if !defined(DART_PRECOMPILED_RUNTIME)
1868 init_params.start_kernel_isolate = dfe.UseDartFrontend();
1869#else
1870 init_params.start_kernel_isolate = false;
1871#endif
Adam Barthfac99f32016-08-09 12:25:29 -07001872
1873 char* error = Dart_Initialize(&init_params);
Zachary Anderson7093f292015-09-15 12:49:52 -07001874 if (error != NULL) {
Florian Schneider63e3f4d2016-07-13 09:41:06 -07001875 EventHandler::Stop();
Ryan Macnak5ee71ca2016-11-22 09:59:06 -08001876 Log::PrintErr("VM initialization failed: %s\n", error);
Zachary Anderson7093f292015-09-15 12:49:52 -07001877 free(error);
Zachary Anderson3563dc02015-10-29 23:35:46 -07001878 Platform::Exit(kErrorExitCode);
johnmccutchan@google.com9b1f39b2015-02-12 21:22:34 +00001879 }
1880
Todd Turnidgee4684c72015-07-14 12:54:07 -07001881 Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
1882 &ServiceStreamCancelCallback);
Todd Turnidge1166f832016-07-29 11:23:18 -07001883 Dart_SetFileModifiedCallback(&FileModifiedCallback);
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -07001884 Dart_SetEmbedderInformationCallback(&EmbedderInformationCallback);
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +00001885
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001886 // Run the main isolate until we aren't told to restart.
1887 while (RunMainIsolate(script_name, &dart_options)) {
1888 Log::PrintErr("Restarting VM\n");
hausner@google.com91593892011-12-07 22:13:49 +00001889 }
hausner@google.com95be4612012-05-04 15:25:49 +00001890
ager@google.comed3338d2012-02-01 18:16:45 +00001891 // Terminate process exit-code handler.
1892 Process::TerminateExitCodeHandler();
ajohnsen@google.com1e2289e2013-07-17 07:26:05 +00001893
Zachary Anderson7093f292015-09-15 12:49:52 -07001894 error = Dart_Cleanup();
1895 if (error != NULL) {
1896 Log::PrintErr("VM cleanup failed: %s\n", error);
1897 free(error);
1898 }
Zachary Anderson89dba572017-03-28 07:44:04 -07001899 Process::ClearAllSignalHandlers();
Florian Schneider63e3f4d2016-07-13 09:41:06 -07001900 EventHandler::Stop();
Zachary Anderson9395a5b2015-09-01 17:53:03 -07001901
Ryan Macnaka317b902017-02-16 13:54:57 -08001902 delete app_snapshot;
Ryan Macnak26a364f2017-01-17 15:59:41 -08001903 free(app_script_uri);
1904
ager@google.com28b43142012-11-13 15:03:23 +00001905 // Free copied argument strings if converted.
1906 if (argv_converted) {
Zachary Andersonc75a8172016-03-14 11:08:52 -07001907 for (int i = 0; i < argc; i++) {
1908 free(argv[i]);
1909 }
ager@google.com28b43142012-11-13 15:03:23 +00001910 }
ager@google.com7031be22012-02-01 14:19:25 +00001911
sgjesse@google.com36a67fa2013-10-31 05:46:57 +00001912 // Free environment if any.
1913 if (environment != NULL) {
Zachary Anderson479a97b2016-11-04 12:30:56 -07001914 for (HashMap::Entry* p = environment->Start(); p != NULL;
sgjesse@google.com36a67fa2013-10-31 05:46:57 +00001915 p = environment->Next(p)) {
1916 free(p->key);
1917 free(p->value);
1918 }
koda@google.com60831f32014-12-23 18:06:31 +00001919 delete environment;
sgjesse@google.com36a67fa2013-10-31 05:46:57 +00001920 }
1921
Zachary Anderson3563dc02015-10-29 23:35:46 -07001922 Platform::Exit(Process::GlobalExitCode());
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001923}
smok@google.comebbc2022013-04-25 14:22:30 +00001924
1925} // namespace bin
1926} // namespace dart
1927
1928int main(int argc, char** argv) {
johnmccutchan@google.coma80d3282013-11-26 18:13:51 +00001929 dart::bin::main(argc, argv);
1930 UNREACHABLE();
smok@google.comebbc2022013-04-25 14:22:30 +00001931}