1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// 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
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include <memory>
10
11#include "bin/builtin.h"
12#include "bin/console.h"
13#include "bin/crashpad.h"
14#include "bin/dartdev_isolate.h"
15#include "bin/dartutils.h"
16#include "bin/dfe.h"
17#include "bin/error_exit.h"
18#include "bin/eventhandler.h"
19#include "bin/extensions.h"
20#include "bin/file.h"
21#include "bin/gzip.h"
22#include "bin/isolate_data.h"
23#include "bin/loader.h"
24#include "bin/main_options.h"
25#include "bin/platform.h"
26#include "bin/process.h"
27#include "bin/snapshot_utils.h"
28#include "bin/thread.h"
29#include "bin/utils.h"
30#include "bin/vmservice_impl.h"
31#include "include/bin/dart_io_api.h"
32#include "include/dart_api.h"
33#include "include/dart_embedder_api.h"
34#include "include/dart_tools_api.h"
35#include "platform/globals.h"
36#include "platform/growable_array.h"
37#include "platform/hashmap.h"
38#include "platform/syslog.h"
39#include "platform/text_buffer.h"
40#include "platform/utils.h"
41
42extern "C" {
43extern const uint8_t kDartVmSnapshotData[];
44extern const uint8_t kDartVmSnapshotInstructions[];
45extern const uint8_t kDartCoreIsolateSnapshotData[];
46extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
47}
48
49namespace dart {
50namespace bin {
51
52// Snapshot pieces we link in a snapshot.
53const uint8_t* vm_snapshot_data = kDartVmSnapshotData;
54const uint8_t* vm_snapshot_instructions = kDartVmSnapshotInstructions;
55const uint8_t* core_isolate_snapshot_data = kDartCoreIsolateSnapshotData;
56const uint8_t* core_isolate_snapshot_instructions =
57 kDartCoreIsolateSnapshotInstructions;
58
59/**
60 * Global state used to control and store generation of application snapshots.
61 * An application snapshot can be generated and run using the following
62 * command
63 * dart --snapshot-kind=app-jit --snapshot=<app_snapshot_filename>
64 * <script_uri> [<script_options>]
65 * To Run the application snapshot generated above, use :
66 * dart <app_snapshot_filename> [<script_options>]
67 */
68static bool vm_run_app_snapshot = false;
69static char* app_script_uri = NULL;
70static const uint8_t* app_isolate_snapshot_data = NULL;
71static const uint8_t* app_isolate_snapshot_instructions = NULL;
72static bool kernel_isolate_is_running = false;
73
74static Dart_Isolate main_isolate = NULL;
75
76static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size);
77
78#define SAVE_ERROR_AND_EXIT(result) \
79 *error = Utils::StrDup(Dart_GetError(result)); \
80 if (Dart_IsCompilationError(result)) { \
81 *exit_code = kCompilationErrorExitCode; \
82 } else if (Dart_IsApiError(result)) { \
83 *exit_code = kApiErrorExitCode; \
84 } else { \
85 *exit_code = kErrorExitCode; \
86 } \
87 Dart_ExitScope(); \
88 Dart_ShutdownIsolate(); \
89 return NULL;
90
91#define CHECK_RESULT(result) \
92 if (Dart_IsError(result)) { \
93 SAVE_ERROR_AND_EXIT(result); \
94 }
95
96#define CHECK_RESULT_CLEANUP(result, cleanup) \
97 if (Dart_IsError(result)) { \
98 delete (cleanup); \
99 SAVE_ERROR_AND_EXIT(result); \
100 }
101
102static void WriteDepsFile(Dart_Isolate isolate) {
103 if (Options::depfile() == NULL) {
104 return;
105 }
106 File* file = File::Open(NULL, Options::depfile(), File::kWriteTruncate);
107 if (file == NULL) {
108 ErrorExit(kErrorExitCode, "Error: Unable to open snapshot depfile: %s\n\n",
109 Options::depfile());
110 }
111 bool success = true;
112 if (Options::snapshot_filename() != NULL) {
113 success &= file->Print("%s: ", Options::snapshot_filename());
114 } else {
115 success &= file->Print("%s: ", Options::depfile_output_filename());
116 }
117 if (kernel_isolate_is_running) {
118 Dart_KernelCompilationResult result = Dart_KernelListDependencies();
119 if (result.status != Dart_KernelCompilationStatus_Ok) {
120 ErrorExit(
121 kErrorExitCode,
122 "Error: Failed to fetch dependencies from kernel service: %s\n\n",
123 result.error);
124 }
125 success &= file->WriteFully(result.kernel, result.kernel_size);
126 free(result.kernel);
127 }
128 success &= file->Print("\n");
129 if (!success) {
130 ErrorExit(kErrorExitCode, "Error: Unable to write snapshot depfile: %s\n\n",
131 Options::depfile());
132 }
133 file->Release();
134}
135
136static void OnExitHook(int64_t exit_code) {
137 if (Dart_CurrentIsolate() != main_isolate) {
138 Syslog::PrintErr(
139 "A snapshot was requested, but a secondary isolate "
140 "performed a hard exit (%" Pd64 ").\n",
141 exit_code);
142 Platform::Exit(kErrorExitCode);
143 }
144 if (exit_code == 0) {
145 if (Options::gen_snapshot_kind() == kAppJIT) {
146 Snapshot::GenerateAppJIT(Options::snapshot_filename());
147 }
148 WriteDepsFile(main_isolate);
149 }
150}
151
152static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
153 IsolateData* isolate_data,
154 bool is_isolate_group_start,
155 const char** resolved_packages_config) {
156 auto isolate_group_data = isolate_data->isolate_group_data();
157 const auto packages_file = isolate_data->packages_file();
158 const auto script_uri = isolate_group_data->script_url;
159
160 Dart_Handle result;
161
162 // Prepare builtin and other core libraries for use to resolve URIs.
163 // Set up various closures, e.g: printing, timers etc.
164 // Set up package configuration for URI resolution.
165 result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
166 if (Dart_IsError(result)) return result;
167
168 // Setup packages config if specified.
169 result = DartUtils::SetupPackageConfig(packages_file);
170 if (Dart_IsError(result)) return result;
171 if (!Dart_IsNull(result) && resolved_packages_config != nullptr) {
172 result = Dart_StringToCString(result, resolved_packages_config);
173 if (Dart_IsError(result)) return result;
174 ASSERT(*resolved_packages_config != nullptr);
175#if !defined(DART_PRECOMPILED_RUNTIME)
176 if (is_isolate_group_start) {
177 isolate_group_data->set_resolved_packages_config(
178 *resolved_packages_config);
179 } else {
180 ASSERT(strcmp(isolate_group_data->resolved_packages_config(),
181 *resolved_packages_config) == 0);
182 }
183#endif
184 }
185
186 result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
187 if (Dart_IsError(result)) return result;
188
189 // Setup the native resolver as the snapshot does not carry it.
190 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
191 Builtin::SetNativeResolver(Builtin::kIOLibrary);
192 Builtin::SetNativeResolver(Builtin::kCLILibrary);
193 VmService::SetNativeResolver();
194
195 const char* namespc =
196 Dart_IsKernelIsolate(isolate) ? NULL : Options::namespc();
197 result =
198 DartUtils::SetupIOLibrary(namespc, script_uri, Options::exit_disabled());
199 if (Dart_IsError(result)) return result;
200
201 return Dart_Null();
202}
203
204static bool OnIsolateInitialize(void** child_callback_data, char** error) {
205 Dart_Isolate isolate = Dart_CurrentIsolate();
206 ASSERT(isolate != nullptr);
207
208 auto isolate_group_data =
209 reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
210
211 auto isolate_data = new IsolateData(isolate_group_data);
212 *child_callback_data = isolate_data;
213
214 Dart_EnterScope();
215 const auto script_uri = isolate_group_data->script_url;
216 const bool isolate_run_app_snapshot =
217 isolate_group_data->RunFromAppSnapshot();
218 Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
219 /*group_start=*/false,
220 /*resolved_packages_config=*/nullptr);
221 if (Dart_IsError(result)) goto failed;
222
223 if (isolate_run_app_snapshot) {
224 result = Loader::InitForSnapshot(script_uri, isolate_data);
225 if (Dart_IsError(result)) goto failed;
226 } else {
227 result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
228 if (Dart_IsError(result)) return result != nullptr;
229
230 if (isolate_group_data->kernel_buffer().get() != nullptr) {
231 // Various core-library parts will send requests to the Loader to resolve
232 // relative URIs and perform other related tasks. We need Loader to be
233 // initialized for this to work because loading from Kernel binary
234 // bypasses normal source code loading paths that initialize it.
235 const char* resolved_script_uri = NULL;
236 result = Dart_StringToCString(result, &resolved_script_uri);
237 if (Dart_IsError(result)) goto failed;
238 result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
239 if (Dart_IsError(result)) goto failed;
240 }
241 }
242
243 if (isolate_run_app_snapshot) {
244 result = Loader::ReloadNativeExtensions();
245 if (Dart_IsError(result)) goto failed;
246 }
247
248 // Make the isolate runnable so that it is ready to handle messages.
249 Dart_ExitScope();
250 Dart_ExitIsolate();
251 *error = Dart_IsolateMakeRunnable(isolate);
252 Dart_EnterIsolate(isolate);
253 return *error == nullptr;
254
255failed:
256 *error = Utils::StrDup(Dart_GetError(result));
257 Dart_ExitScope();
258 return false;
259}
260
261static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
262 bool is_main_isolate,
263 const char* script_uri,
264 const char* packages_config,
265 bool isolate_run_app_snapshot,
266 Dart_IsolateFlags* flags,
267 char** error,
268 int* exit_code) {
269 Dart_EnterScope();
270
271 // Set up the library tag handler for the isolate group shared by all
272 // isolates in the group.
273 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
274 CHECK_RESULT(result);
275 result = Dart_SetDeferredLoadHandler(Loader::DeferredLoadHandler);
276 CHECK_RESULT(result);
277
278 auto isolate_data = reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
279
280 const char* resolved_packages_config = nullptr;
281 result = SetupCoreLibraries(isolate, isolate_data,
282 /*is_isolate_group_start=*/true,
283 &resolved_packages_config);
284 CHECK_RESULT(result);
285
286#if !defined(DART_PRECOMPILED_RUNTIME)
287 auto isolate_group_data = isolate_data->isolate_group_data();
288 const uint8_t* kernel_buffer = isolate_group_data->kernel_buffer().get();
289 intptr_t kernel_buffer_size = isolate_group_data->kernel_buffer_size();
290 if (!isolate_run_app_snapshot && kernel_buffer == NULL &&
291 !Dart_IsKernelIsolate(isolate)) {
292 if (!dfe.CanUseDartFrontend()) {
293 const char* format = "Dart frontend unavailable to compile script %s.";
294 intptr_t len = snprintf(NULL, 0, format, script_uri) + 1;
295 *error = reinterpret_cast<char*>(malloc(len));
296 ASSERT(error != NULL);
297 snprintf(*error, len, format, script_uri);
298 *exit_code = kErrorExitCode;
299 Dart_ExitScope();
300 Dart_ShutdownIsolate();
301 return NULL;
302 }
303 uint8_t* application_kernel_buffer = NULL;
304 intptr_t application_kernel_buffer_size = 0;
305 dfe.CompileAndReadScript(script_uri, &application_kernel_buffer,
306 &application_kernel_buffer_size, error, exit_code,
307 resolved_packages_config);
308 if (application_kernel_buffer == NULL) {
309 Dart_ExitScope();
310 Dart_ShutdownIsolate();
311 return NULL;
312 }
313 isolate_group_data->SetKernelBufferNewlyOwned(
314 application_kernel_buffer, application_kernel_buffer_size);
315 kernel_buffer = application_kernel_buffer;
316 kernel_buffer_size = application_kernel_buffer_size;
317 }
318 if (kernel_buffer != NULL) {
319 Dart_Handle uri = Dart_NewStringFromCString(script_uri);
320 CHECK_RESULT(uri);
321 Dart_Handle resolved_script_uri = DartUtils::ResolveScript(uri);
322 CHECK_RESULT(resolved_script_uri);
323 result = Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
324 CHECK_RESULT(result);
325 }
326#endif // !defined(DART_PRECOMPILED_RUNTIME)
327
328 if (isolate_run_app_snapshot) {
329 Dart_Handle result = Loader::ReloadNativeExtensions();
330 CHECK_RESULT(result);
331 }
332
333 if (isolate_run_app_snapshot) {
334 Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data);
335 CHECK_RESULT(result);
336#if !defined(DART_PRECOMPILED_RUNTIME)
337 if (is_main_isolate) {
338 // Find the canonical uri of the app snapshot. We'll use this to decide if
339 // other isolates should use the app snapshot or the core snapshot.
340 const char* resolved_script_uri = NULL;
341 result = Dart_StringToCString(
342 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri)),
343 &resolved_script_uri);
344 CHECK_RESULT(result);
345 ASSERT(app_script_uri == NULL);
346 app_script_uri = Utils::StrDup(resolved_script_uri);
347 }
348#endif // !defined(DART_PRECOMPILED_RUNTIME)
349 } else {
350#if !defined(DART_PRECOMPILED_RUNTIME)
351 // Load the specified application script into the newly created isolate.
352 Dart_Handle uri =
353 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
354 CHECK_RESULT(uri);
355 if (kernel_buffer != NULL) {
356 // relative URIs and perform other related tasks. We need Loader to be
357 // initialized for this to work because loading from Kernel binary
358 // bypasses normal source code loading paths that initialize it.
359 const char* resolved_script_uri = NULL;
360 result = Dart_StringToCString(uri, &resolved_script_uri);
361 CHECK_RESULT(result);
362 result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
363 CHECK_RESULT(result);
364 }
365 Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
366 Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
367 NULL, NULL);
368#else
369 UNREACHABLE();
370#endif // !defined(DART_PRECOMPILED_RUNTIME)
371 }
372
373 if (Options::gen_snapshot_kind() == kAppJIT) {
374 // If we sort, we must do it for all isolates, not just the main isolate,
375 // otherwise isolates related by spawnFunction will disagree on CIDs and
376 // cannot correctly send each other messages.
377 result = Dart_SortClasses();
378 CHECK_RESULT(result);
379 }
380
381 // Disable pausing the DartDev isolate on start and exit.
382 const char* isolate_name = nullptr;
383 result = Dart_StringToCString(Dart_DebugName(), &isolate_name);
384 CHECK_RESULT(result);
385 if (strstr(isolate_name, "dartdev") != nullptr) {
386 Dart_SetShouldPauseOnStart(false);
387 Dart_SetShouldPauseOnExit(false);
388 }
389
390 // Make the isolate runnable so that it is ready to handle messages.
391 Dart_ExitScope();
392 Dart_ExitIsolate();
393 *error = Dart_IsolateMakeRunnable(isolate);
394 if (*error != NULL) {
395 Dart_EnterIsolate(isolate);
396 Dart_ShutdownIsolate();
397 return NULL;
398 }
399
400 return isolate;
401}
402
403#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
404// Returns newly created Kernel Isolate on success, NULL on failure.
405// For now we only support the kernel isolate coming up from an
406// application snapshot or from a .dill file.
407static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
408 const char* packages_config,
409 Dart_IsolateFlags* flags,
410 char** error,
411 int* exit_code) {
412 // Do not start a kernel isolate if we are doing a training run
413 // to create an app JIT snapshot and a kernel file is specified
414 // as the application to run.
415 if (Options::gen_snapshot_kind() == kAppJIT) {
416 const uint8_t* kernel_buffer = NULL;
417 intptr_t kernel_buffer_size = 0;
418 dfe.application_kernel_buffer(&kernel_buffer, &kernel_buffer_size);
419 if (kernel_buffer_size != 0) {
420 return NULL;
421 }
422 }
423 // Create and Start the kernel isolate.
424 const char* kernel_snapshot_uri = dfe.frontend_filename();
425 const char* uri =
426 kernel_snapshot_uri != NULL ? kernel_snapshot_uri : script_uri;
427
428 if (packages_config == NULL) {
429 packages_config = Options::packages_file();
430 }
431
432 Dart_Isolate isolate = NULL;
433 IsolateGroupData* isolate_group_data = nullptr;
434 IsolateData* isolate_data = nullptr;
435 bool isolate_run_app_snapshot = false;
436 AppSnapshot* app_snapshot = NULL;
437 // Kernel isolate uses an app snapshot or uses the dill file.
438 if ((kernel_snapshot_uri != NULL) &&
439 (app_snapshot = Snapshot::TryReadAppSnapshot(kernel_snapshot_uri)) !=
440 NULL) {
441 const uint8_t* isolate_snapshot_data = NULL;
442 const uint8_t* isolate_snapshot_instructions = NULL;
443 const uint8_t* ignore_vm_snapshot_data;
444 const uint8_t* ignore_vm_snapshot_instructions;
445 isolate_run_app_snapshot = true;
446 app_snapshot->SetBuffers(
447 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
448 &isolate_snapshot_data, &isolate_snapshot_instructions);
449 isolate_group_data = new IsolateGroupData(
450 uri, packages_config, app_snapshot, isolate_run_app_snapshot);
451 isolate_data = new IsolateData(isolate_group_data);
452 isolate = Dart_CreateIsolateGroup(
453 DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
454 isolate_snapshot_data, isolate_snapshot_instructions, flags,
455 isolate_group_data, isolate_data, error);
456 }
457 if (isolate == NULL) {
458 // Clear error from app snapshot and re-trying from kernel file.
459 free(*error);
460 *error = NULL;
461 delete isolate_data;
462 delete isolate_group_data;
463
464 const uint8_t* kernel_service_buffer = NULL;
465 intptr_t kernel_service_buffer_size = 0;
466 dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size);
467 ASSERT(kernel_service_buffer != NULL);
468 isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr,
469 isolate_run_app_snapshot);
470 isolate_group_data->SetKernelBufferUnowned(
471 const_cast<uint8_t*>(kernel_service_buffer),
472 kernel_service_buffer_size);
473 isolate_data = new IsolateData(isolate_group_data);
474 isolate = Dart_CreateIsolateGroupFromKernel(
475 DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
476 kernel_service_buffer, kernel_service_buffer_size, flags,
477 isolate_group_data, isolate_data, error);
478 }
479
480 if (isolate == NULL) {
481 Syslog::PrintErr("%s\n", *error);
482 delete isolate_data;
483 delete isolate_group_data;
484 return NULL;
485 }
486 kernel_isolate_is_running = true;
487
488 return IsolateSetupHelper(isolate, false, uri, packages_config,
489 isolate_run_app_snapshot, flags, error, exit_code);
490}
491#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
492
493// Returns newly created Service Isolate on success, NULL on failure.
494// For now we only support the service isolate coming up from sources
495// which are compiled by the VM parser.
496static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
497 const char* packages_config,
498 Dart_IsolateFlags* flags,
499 char** error,
500 int* exit_code) {
501#if !defined(PRODUCT)
502 ASSERT(script_uri != nullptr);
503 Dart_Isolate isolate = nullptr;
504 auto isolate_group_data =
505 new IsolateGroupData(script_uri, packages_config, nullptr, false);
506 ASSERT(flags != nullptr);
507
508#if defined(DART_PRECOMPILED_RUNTIME)
509 // AOT: All isolates start from the app snapshot.
510 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
511 const uint8_t* isolate_snapshot_instructions =
512 app_isolate_snapshot_instructions;
513 flags->null_safety =
514 Dart_DetectNullSafety(nullptr, nullptr, nullptr, isolate_snapshot_data,
515 isolate_snapshot_instructions, nullptr, -1);
516 isolate = Dart_CreateIsolateGroup(
517 script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
518 isolate_snapshot_instructions, flags, isolate_group_data,
519 /*isolate_data=*/nullptr, error);
520#else
521 // JIT: Service isolate uses the core libraries snapshot.
522
523 // Set flag to load and retain the vmservice library.
524 flags->load_vmservice_library = true;
525 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
526 const uint8_t* isolate_snapshot_instructions =
527 core_isolate_snapshot_instructions;
528 isolate = Dart_CreateIsolateGroup(
529 script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
530 isolate_snapshot_instructions, flags, isolate_group_data,
531 /*isolate_data=*/nullptr, error);
532#endif // !defined(DART_PRECOMPILED_RUNTIME)
533 if (isolate == NULL) {
534 delete isolate_group_data;
535 return NULL;
536 }
537
538 Dart_EnterScope();
539
540 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
541 CHECK_RESULT(result);
542 result = Dart_SetDeferredLoadHandler(Loader::DeferredLoadHandler);
543 CHECK_RESULT(result);
544
545 // Load embedder specific bits and return.
546 if (!VmService::Setup(
547 Options::vm_service_server_ip(), Options::vm_service_server_port(),
548 Options::vm_service_dev_mode(), Options::vm_service_auth_disabled(),
549 Options::vm_write_service_info_filename(), Options::trace_loading(),
550 Options::deterministic(), Options::enable_service_port_fallback())) {
551 *error = Utils::StrDup(VmService::GetErrorMessage());
552 return NULL;
553 }
554 if (Options::compile_all()) {
555 result = Dart_CompileAll();
556 CHECK_RESULT(result);
557 }
558 result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
559 CHECK_RESULT(result);
560 Dart_ExitScope();
561 Dart_ExitIsolate();
562 return isolate;
563#else // !defined(PRODUCT)
564 return NULL;
565#endif // !defined(PRODUCT)
566}
567
568// Returns newly created Isolate on success, NULL on failure.
569static Dart_Isolate CreateIsolateGroupAndSetupHelper(
570 bool is_main_isolate,
571 const char* script_uri,
572 const char* name,
573 const char* packages_config,
574 Dart_IsolateFlags* flags,
575 void* callback_data,
576 char** error,
577 int* exit_code) {
578 int64_t start = Dart_TimelineGetMicros();
579 ASSERT(script_uri != NULL);
580 uint8_t* kernel_buffer = NULL;
581 std::shared_ptr<uint8_t> parent_kernel_buffer;
582 intptr_t kernel_buffer_size = 0;
583 AppSnapshot* app_snapshot = NULL;
584
585#if defined(DART_PRECOMPILED_RUNTIME)
586 // AOT: All isolates start from the app snapshot.
587 bool isolate_run_app_snapshot = true;
588 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
589 const uint8_t* isolate_snapshot_instructions =
590 app_isolate_snapshot_instructions;
591 flags->null_safety =
592 Dart_DetectNullSafety(nullptr, nullptr, nullptr, isolate_snapshot_data,
593 isolate_snapshot_instructions, nullptr, -1);
594#else
595 // JIT: Main isolate starts from the app snapshot, if any. Other isolates
596 // use the core libraries snapshot.
597 bool isolate_run_app_snapshot = false;
598 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
599 const uint8_t* isolate_snapshot_instructions =
600 core_isolate_snapshot_instructions;
601 if ((app_isolate_snapshot_data != NULL) &&
602 (is_main_isolate || ((app_script_uri != NULL) &&
603 (strcmp(script_uri, app_script_uri) == 0)))) {
604 isolate_run_app_snapshot = true;
605 isolate_snapshot_data = app_isolate_snapshot_data;
606 isolate_snapshot_instructions = app_isolate_snapshot_instructions;
607 } else if (!is_main_isolate) {
608 app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
609 if (app_snapshot != NULL) {
610 isolate_run_app_snapshot = true;
611 const uint8_t* ignore_vm_snapshot_data;
612 const uint8_t* ignore_vm_snapshot_instructions;
613 app_snapshot->SetBuffers(
614 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
615 &isolate_snapshot_data, &isolate_snapshot_instructions);
616 }
617 }
618
619 if (flags->copy_parent_code && callback_data != nullptr) {
620 auto parent_isolate_group_data =
621 reinterpret_cast<IsolateData*>(callback_data)->isolate_group_data();
622 parent_kernel_buffer = parent_isolate_group_data->kernel_buffer();
623 kernel_buffer = parent_kernel_buffer.get();
624 kernel_buffer_size = parent_isolate_group_data->kernel_buffer_size();
625 }
626
627 if (kernel_buffer == NULL && !isolate_run_app_snapshot) {
628 dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size);
629 }
630 PathSanitizer script_uri_sanitizer(script_uri);
631 PathSanitizer packages_config_sanitizer(packages_config);
632 flags->null_safety = Dart_DetectNullSafety(
633 script_uri_sanitizer.sanitized_uri(),
634 packages_config_sanitizer.sanitized_uri(),
635 DartUtils::original_working_directory, isolate_snapshot_data,
636 isolate_snapshot_instructions, kernel_buffer, kernel_buffer_size);
637#endif // !defined(DART_PRECOMPILED_RUNTIME)
638
639 auto isolate_group_data = new IsolateGroupData(
640 script_uri, packages_config, app_snapshot, isolate_run_app_snapshot);
641 if (kernel_buffer != NULL) {
642 if (parent_kernel_buffer) {
643 isolate_group_data->SetKernelBufferAlreadyOwned(
644 std::move(parent_kernel_buffer), kernel_buffer_size);
645 } else {
646 isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer,
647 kernel_buffer_size);
648 }
649 }
650
651 Dart_Isolate isolate = NULL;
652
653#if !defined(DART_PRECOMPILED_RUNTIME)
654 if (!isolate_run_app_snapshot && (isolate_snapshot_data == NULL)) {
655 const uint8_t* platform_kernel_buffer = NULL;
656 intptr_t platform_kernel_buffer_size = 0;
657 dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size);
658 if (platform_kernel_buffer == NULL) {
659 platform_kernel_buffer = kernel_buffer;
660 platform_kernel_buffer_size = kernel_buffer_size;
661 }
662 if (platform_kernel_buffer == NULL) {
663#if defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
664 FATAL(
665 "Binary built with --exclude-kernel-service. Cannot run"
666 " from source.");
667#else
668 FATAL("platform_program cannot be NULL.");
669#endif // defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
670 }
671 // TODO(sivachandra): When the platform program is unavailable, check if
672 // application kernel binary is self contained or an incremental binary.
673 // Isolate should be created only if it is a self contained kernel binary.
674 auto isolate_data = new IsolateData(isolate_group_data);
675 isolate = Dart_CreateIsolateGroupFromKernel(
676 script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size,
677 flags, isolate_group_data, isolate_data, error);
678 } else {
679 auto isolate_data = new IsolateData(isolate_group_data);
680 isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
681 isolate_snapshot_instructions, flags,
682 isolate_group_data, isolate_data, error);
683 }
684#else
685 auto isolate_data = new IsolateData(isolate_group_data);
686 isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
687 isolate_snapshot_instructions, flags,
688 isolate_group_data, isolate_data, error);
689#endif // !defined(DART_PRECOMPILED_RUNTIME)
690
691 Dart_Isolate created_isolate = NULL;
692 if (isolate == NULL) {
693 delete isolate_group_data;
694 } else {
695 created_isolate = IsolateSetupHelper(
696 isolate, is_main_isolate, script_uri, packages_config,
697 isolate_run_app_snapshot, flags, error, exit_code);
698 }
699 int64_t end = Dart_TimelineGetMicros();
700 Dart_TimelineEvent("CreateIsolateGroupAndSetupHelper", start, end,
701 Dart_Timeline_Event_Duration, 0, NULL, NULL);
702 return created_isolate;
703}
704
705#undef CHECK_RESULT
706
707static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
708 const char* main,
709 const char* package_root,
710 const char* package_config,
711 Dart_IsolateFlags* flags,
712 void* callback_data,
713 char** error) {
714 // The VM should never call the isolate helper with a NULL flags.
715 ASSERT(flags != NULL);
716 ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION);
717 ASSERT(package_root == nullptr);
718 int exit_code = 0;
719#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
720 if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
721 return CreateAndSetupKernelIsolate(script_uri, package_config, flags, error,
722 &exit_code);
723 }
724#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
725 if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
726 return CreateAndSetupServiceIsolate(script_uri, package_config, flags,
727 error, &exit_code);
728 }
729 bool is_main_isolate = false;
730 return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main,
731 package_config, flags, callback_data,
732 error, &exit_code);
733}
734
735static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
736 Dart_EnterScope();
737 Dart_Handle sticky_error = Dart_GetStickyError();
738 if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
739 Syslog::PrintErr("%s\n", Dart_GetError(sticky_error));
740 }
741 Dart_ExitScope();
742}
743
744static void DeleteIsolateData(void* isolate_group_data, void* callback_data) {
745 auto isolate_data = reinterpret_cast<IsolateData*>(callback_data);
746 delete isolate_data;
747}
748
749static void DeleteIsolateGroupData(void* callback_data) {
750 auto isolate_group_data = reinterpret_cast<IsolateGroupData*>(callback_data);
751 delete isolate_group_data;
752}
753
754static const char* kStdoutStreamId = "Stdout";
755static const char* kStderrStreamId = "Stderr";
756
757static bool ServiceStreamListenCallback(const char* stream_id) {
758 if (strcmp(stream_id, kStdoutStreamId) == 0) {
759 SetCaptureStdout(true);
760 return true;
761 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
762 SetCaptureStderr(true);
763 return true;
764 }
765 return false;
766}
767
768static void ServiceStreamCancelCallback(const char* stream_id) {
769 if (strcmp(stream_id, kStdoutStreamId) == 0) {
770 SetCaptureStdout(false);
771 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
772 SetCaptureStderr(false);
773 }
774}
775
776static bool FileModifiedCallback(const char* url, int64_t since) {
777 if (strncmp(url, "file:///", 8) != 0) {
778 // If it isn't a file on local disk, we don't know if it has been
779 // modified.
780 return true;
781 }
782 int64_t data[File::kStatSize];
783 File::Stat(NULL, url + 7, data);
784 if (data[File::kType] == File::kDoesNotExist) {
785 return true;
786 }
787 bool modified = data[File::kModifiedTime] > since;
788 return modified;
789}
790
791static void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
792 info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
793 info->name = "Dart VM";
794 Process::GetRSSInformation(&(info->max_rss), &(info->current_rss));
795}
796
797#define CHECK_RESULT(result) \
798 if (Dart_IsError(result)) { \
799 const int exit_code = Dart_IsCompilationError(result) \
800 ? kCompilationErrorExitCode \
801 : kErrorExitCode; \
802 ErrorExit(exit_code, "%s\n", Dart_GetError(result)); \
803 }
804
805static void WriteFile(const char* filename,
806 const uint8_t* buffer,
807 const intptr_t size) {
808 File* file = File::Open(NULL, filename, File::kWriteTruncate);
809 if (file == NULL) {
810 ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename);
811 }
812 if (!file->WriteFully(buffer, size)) {
813 ErrorExit(kErrorExitCode, "Unable to write file %s\n", filename);
814 }
815 file->Release();
816}
817
818static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) {
819 File* file = File::Open(NULL, filename, File::kRead);
820 if (file == NULL) {
821 ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename);
822 }
823 *size = file->Length();
824 *buffer = reinterpret_cast<uint8_t*>(malloc(*size));
825 if (!file->ReadFully(*buffer, *size)) {
826 ErrorExit(kErrorExitCode, "Unable to read file %s\n", filename);
827 }
828 file->Release();
829}
830
831bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
832 // Call CreateIsolateGroupAndSetup which creates an isolate and loads up
833 // the specified application script.
834 char* error = NULL;
835 bool is_main_isolate = true;
836 int exit_code = 0;
837 Dart_IsolateFlags flags;
838 Dart_IsolateFlagsInitialize(&flags);
839
840 Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
841 is_main_isolate, script_name, "main", Options::packages_file(), &flags,
842 NULL /* callback_data */, &error, &exit_code);
843
844 if (isolate == NULL) {
845 Syslog::PrintErr("%s\n", error);
846 free(error);
847 error = NULL;
848 Process::TerminateExitCodeHandler();
849 error = Dart_Cleanup();
850 if (error != NULL) {
851 Syslog::PrintErr("VM cleanup failed: %s\n", error);
852 free(error);
853 }
854 dart::embedder::Cleanup();
855 Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
856 }
857 main_isolate = isolate;
858
859 Dart_EnterIsolate(isolate);
860 ASSERT(isolate == Dart_CurrentIsolate());
861 ASSERT(isolate != NULL);
862 Dart_Handle result;
863
864 Dart_EnterScope();
865
866 auto isolate_group_data =
867 reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
868 if (Options::gen_snapshot_kind() == kKernel) {
869 if (vm_run_app_snapshot) {
870 Syslog::PrintErr(
871 "Cannot create a script snapshot from an app snapshot.\n");
872 // The snapshot would contain references to the app snapshot instead of
873 // the core snapshot.
874 Platform::Exit(kErrorExitCode);
875 }
876 Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
877 isolate_group_data->resolved_packages_config());
878 } else {
879 // Lookup the library of the root script.
880 Dart_Handle root_lib = Dart_RootLibrary();
881
882#if !defined(DART_PRECOMPILED_RUNTIME)
883 if (Options::compile_all()) {
884 result = Dart_CompileAll();
885 CHECK_RESULT(result);
886 }
887#endif // !defined(DART_PRECOMPILED_RUNTIME)
888
889 if (Dart_IsNull(root_lib)) {
890 ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
891 script_name);
892 }
893
894 if (Options::load_compilation_trace_filename() != NULL) {
895 uint8_t* buffer = NULL;
896 intptr_t size = 0;
897 ReadFile(Options::load_compilation_trace_filename(), &buffer, &size);
898 result = Dart_LoadCompilationTrace(buffer, size);
899 free(buffer);
900 CHECK_RESULT(result);
901 }
902 if (Options::load_type_feedback_filename() != NULL) {
903 uint8_t* buffer = NULL;
904 intptr_t size = 0;
905 ReadFile(Options::load_type_feedback_filename(), &buffer, &size);
906 result = Dart_LoadTypeFeedback(buffer, size);
907 free(buffer);
908 CHECK_RESULT(result);
909 }
910
911 // Create a closure for the main entry point which is in the exported
912 // namespace of the root library or invoke a getter of the same name
913 // in the exported namespace and return the resulting closure.
914 Dart_Handle main_closure =
915 Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
916 CHECK_RESULT(main_closure);
917 if (!Dart_IsClosure(main_closure)) {
918 ErrorExit(kErrorExitCode, "Unable to find 'main' in root library '%s'\n",
919 script_name);
920 }
921
922 // Call _startIsolate in the isolate library to enable dispatching the
923 // initial startup message.
924 const intptr_t kNumIsolateArgs = 2;
925 Dart_Handle isolate_args[kNumIsolateArgs];
926 isolate_args[0] = main_closure; // entryPoint
927 isolate_args[1] = dart_options->CreateRuntimeOptions(); // args
928
929 Dart_Handle isolate_lib =
930 Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
931 result =
932 Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startMainIsolate"),
933 kNumIsolateArgs, isolate_args);
934 CHECK_RESULT(result);
935
936 // Keep handling messages until the last active receive port is closed.
937 result = Dart_RunLoop();
938 // Generate an app snapshot after execution if specified.
939 if (Options::gen_snapshot_kind() == kAppJIT) {
940 if (!Dart_IsCompilationError(result)) {
941 Snapshot::GenerateAppJIT(Options::snapshot_filename());
942 }
943 }
944 CHECK_RESULT(result);
945
946 if (Options::save_compilation_trace_filename() != NULL) {
947 uint8_t* buffer = NULL;
948 intptr_t size = 0;
949 result = Dart_SaveCompilationTrace(&buffer, &size);
950 CHECK_RESULT(result);
951 WriteFile(Options::save_compilation_trace_filename(), buffer, size);
952 }
953 if (Options::save_type_feedback_filename() != NULL) {
954 uint8_t* buffer = NULL;
955 intptr_t size = 0;
956 result = Dart_SaveTypeFeedback(&buffer, &size);
957 CHECK_RESULT(result);
958 WriteFile(Options::save_type_feedback_filename(), buffer, size);
959 }
960 }
961
962 WriteDepsFile(isolate);
963
964 Dart_ExitScope();
965
966 // Shutdown the isolate.
967 Dart_ShutdownIsolate();
968
969 // No restart.
970 return false;
971}
972
973#undef CHECK_RESULT
974
975static bool CheckForInvalidPath(const char* path) {
976 // TODO(zichangguo): "\\?\" is a prefix for paths on Windows.
977 // Arguments passed are parsed as an URI. "\\?\" causes problems as a part
978 // of URIs. This is a temporary workaround to prevent VM from crashing.
979 // Issue: https://github.com/dart-lang/sdk/issues/42779
980 if (strncmp(path, "\\\\?\\", 4) == 0) {
981 Syslog::PrintErr("\\\\?\\ prefix is not supported");
982 return false;
983 }
984 return true;
985}
986
987// Observatory assets are not included in a product build.
988#if !defined(PRODUCT)
989extern unsigned int observatory_assets_archive_len;
990extern const uint8_t* observatory_assets_archive;
991
992Dart_Handle GetVMServiceAssetsArchiveCallback() {
993 uint8_t* decompressed = NULL;
994 intptr_t decompressed_len = 0;
995 Decompress(observatory_assets_archive, observatory_assets_archive_len,
996 &decompressed, &decompressed_len);
997 Dart_Handle tar_file =
998 DartUtils::MakeUint8Array(decompressed, decompressed_len);
999 // Free decompressed memory as it has been copied into a Dart array.
1000 free(decompressed);
1001 return tar_file;
1002}
1003#else // !defined(PRODUCT)
1004static Dart_GetVMServiceAssetsArchive GetVMServiceAssetsArchiveCallback = NULL;
1005#endif // !defined(PRODUCT)
1006
1007void main(int argc, char** argv) {
1008 char* script_name = nullptr;
1009 const int EXTRA_VM_ARGUMENTS = 10;
1010 CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
1011 CommandLineOptions dart_options(argc + EXTRA_VM_ARGUMENTS);
1012 bool print_flags_seen = false;
1013 bool verbose_debug_seen = false;
1014
1015 // Perform platform specific initialization.
1016 if (!Platform::Initialize()) {
1017 Syslog::PrintErr("Initialization failed\n");
1018 Platform::Exit(kErrorExitCode);
1019 }
1020
1021 // Save the console state so we can restore it at shutdown.
1022 Console::SaveConfig();
1023
1024 // On Windows, the argv strings are code page encoded and not
1025 // utf8. We need to convert them to utf8.
1026 bool argv_converted = ShellUtils::GetUtf8Argv(argc, argv);
1027
1028#if !defined(DART_PRECOMPILED_RUNTIME)
1029 // Processing of some command line flags directly manipulates dfe.
1030 Options::set_dfe(&dfe);
1031#endif // !defined(DART_PRECOMPILED_RUNTIME)
1032
1033 // When running from the command line we assume that we are optimizing for
1034 // throughput, and therefore use a larger new gen semi space size and a faster
1035 // new gen growth factor unless others have been specified.
1036 if (kWordSize <= 4) {
1037 vm_options.AddArgument("--new_gen_semi_max_size=16");
1038 } else {
1039 vm_options.AddArgument("--new_gen_semi_max_size=32");
1040 }
1041 vm_options.AddArgument("--new_gen_growth_factor=4");
1042
1043 AppSnapshot* app_snapshot = nullptr;
1044#if defined(DART_PRECOMPILED_RUNTIME)
1045 // If the executable binary contains the runtime together with an appended
1046 // snapshot, load and run that.
1047 // Any arguments passed to such an executable are meant for the actual
1048 // application so skip all Dart VM flag parsing.
1049
1050 const size_t kPathBufSize = PATH_MAX + 1;
1051 char executable_path[kPathBufSize];
1052 if (Platform::ResolveExecutablePathInto(executable_path, kPathBufSize) > 0) {
1053 app_snapshot = Snapshot::TryReadAppendedAppSnapshotElf(executable_path);
1054 if (app_snapshot != nullptr) {
1055 script_name = argv[0];
1056
1057 // Store the executable name.
1058 Platform::SetExecutableName(argv[0]);
1059
1060 // Parse out options to be passed to dart main.
1061 for (int i = 1; i < argc; i++) {
1062 dart_options.AddArgument(argv[i]);
1063 }
1064 }
1065 }
1066#endif
1067
1068 // Parse command line arguments.
1069 if (app_snapshot == nullptr) {
1070 int result = Options::ParseArguments(
1071 argc, argv, vm_run_app_snapshot, &vm_options, &script_name,
1072 &dart_options, &print_flags_seen, &verbose_debug_seen);
1073 if (result < 0) {
1074 if (Options::help_option()) {
1075 Options::PrintUsage();
1076 Platform::Exit(0);
1077 } else if (Options::version_option()) {
1078 Options::PrintVersion();
1079 Platform::Exit(0);
1080 } else if (print_flags_seen) {
1081 // Will set the VM flags, print them out and then we exit as no
1082 // script was specified on the command line.
1083 char* error =
1084 Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
1085 if (error != NULL) {
1086 Syslog::PrintErr("Setting VM flags failed: %s\n", error);
1087 free(error);
1088 Platform::Exit(kErrorExitCode);
1089 }
1090 Platform::Exit(0);
1091 } else {
1092 Options::PrintUsage();
1093 Platform::Exit(kErrorExitCode);
1094 }
1095 }
1096 }
1097
1098 DartUtils::SetEnvironment(Options::environment());
1099
1100 if (Options::suppress_core_dump()) {
1101 Platform::SetCoreDumpResourceLimit(0);
1102 } else {
1103 InitializeCrashpadClient();
1104 }
1105
1106 Loader::InitOnce();
1107
1108 auto try_load_snapshots_lambda = [&](void) -> void {
1109 if (app_snapshot == nullptr) {
1110 // For testing purposes we add a flag to debug-mode to use the
1111 // in-memory ELF loader.
1112 const bool force_load_elf_from_memory =
1113 false DEBUG_ONLY(|| Options::force_load_elf_from_memory());
1114 app_snapshot =
1115 Snapshot::TryReadAppSnapshot(script_name, force_load_elf_from_memory);
1116 }
1117 if (app_snapshot != nullptr) {
1118 vm_run_app_snapshot = true;
1119 app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
1120 &app_isolate_snapshot_data,
1121 &app_isolate_snapshot_instructions);
1122 }
1123 };
1124
1125 // At this point, script_name now points to a script if DartDev is disabled
1126 // or a valid file path was provided as the first non-flag argument.
1127 // Otherwise, script_name can be NULL if DartDev should be run.
1128 if (script_name != nullptr) {
1129 if (!CheckForInvalidPath(script_name)) {
1130 Platform::Exit(0);
1131 }
1132 try_load_snapshots_lambda();
1133 }
1134
1135 if (Options::gen_snapshot_kind() == kAppJIT) {
1136 vm_options.AddArgument("--fields_may_be_reset");
1137 }
1138#if defined(DART_PRECOMPILED_RUNTIME)
1139 vm_options.AddArgument("--precompilation");
1140#endif
1141 // If we need to write an app-jit snapshot or a depfile, then add an exit
1142 // hook that writes the snapshot and/or depfile as appropriate.
1143 if ((Options::gen_snapshot_kind() == kAppJIT) ||
1144 (Options::depfile() != NULL)) {
1145 Process::SetExitHook(OnExitHook);
1146 }
1147
1148 char* error = nullptr;
1149 if (!dart::embedder::InitOnce(&error)) {
1150 Syslog::PrintErr("Standalone embedder initialization failed: %s\n", error);
1151 free(error);
1152 Platform::Exit(kErrorExitCode);
1153 }
1154
1155 error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
1156 if (error != NULL) {
1157 Syslog::PrintErr("Setting VM flags failed: %s\n", error);
1158 free(error);
1159 Platform::Exit(kErrorExitCode);
1160 }
1161
1162// Note: must read platform only *after* VM flags are parsed because
1163// they might affect how the platform is loaded.
1164#if !defined(DART_PRECOMPILED_RUNTIME)
1165 if (script_name != nullptr) {
1166 dfe.Init();
1167 uint8_t* application_kernel_buffer = NULL;
1168 intptr_t application_kernel_buffer_size = 0;
1169 dfe.ReadScript(script_name, &application_kernel_buffer,
1170 &application_kernel_buffer_size);
1171 if (application_kernel_buffer != NULL) {
1172 // Since we loaded the script anyway, save it.
1173 dfe.set_application_kernel_buffer(application_kernel_buffer,
1174 application_kernel_buffer_size);
1175 Options::dfe()->set_use_dfe();
1176 }
1177 }
1178#endif
1179
1180 // Initialize the Dart VM.
1181 Dart_InitializeParams init_params;
1182 memset(&init_params, 0, sizeof(init_params));
1183 init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
1184 init_params.vm_snapshot_data = vm_snapshot_data;
1185 init_params.vm_snapshot_instructions = vm_snapshot_instructions;
1186 init_params.create_group = CreateIsolateGroupAndSetup;
1187 init_params.initialize_isolate = OnIsolateInitialize;
1188 init_params.shutdown_isolate = OnIsolateShutdown;
1189 init_params.cleanup_isolate = DeleteIsolateData;
1190 init_params.cleanup_group = DeleteIsolateGroupData;
1191 init_params.file_open = DartUtils::OpenFile;
1192 init_params.file_read = DartUtils::ReadFile;
1193 init_params.file_write = DartUtils::WriteFile;
1194 init_params.file_close = DartUtils::CloseFile;
1195 init_params.entropy_source = DartUtils::EntropySource;
1196 init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
1197#if !defined(DART_PRECOMPILED_RUNTIME)
1198 init_params.start_kernel_isolate =
1199 dfe.UseDartFrontend() && dfe.CanUseDartFrontend();
1200#else
1201 init_params.start_kernel_isolate = false;
1202#endif
1203
1204 error = Dart_Initialize(&init_params);
1205 if (error != NULL) {
1206 dart::embedder::Cleanup();
1207 Syslog::PrintErr("VM initialization failed: %s\n", error);
1208 free(error);
1209 Platform::Exit(kErrorExitCode);
1210 }
1211
1212 Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
1213 &ServiceStreamCancelCallback);
1214 Dart_SetFileModifiedCallback(&FileModifiedCallback);
1215 Dart_SetEmbedderInformationCallback(&EmbedderInformationCallback);
1216 bool ran_dart_dev = false;
1217 bool should_run_user_program = true;
1218#if !defined(DART_PRECOMPILED_RUNTIME)
1219 if (DartDevIsolate::should_run_dart_dev() && !Options::disable_dart_dev() &&
1220 Options::gen_snapshot_kind() == SnapshotKind::kNone) {
1221 DartDevIsolate::DartDev_Result dartdev_result = DartDevIsolate::RunDartDev(
1222 CreateIsolateGroupAndSetup, Options::packages_file(), &script_name,
1223 &dart_options);
1224 ASSERT(dartdev_result != DartDevIsolate::DartDev_Result_Unknown);
1225 ran_dart_dev = true;
1226 should_run_user_program =
1227 (dartdev_result == DartDevIsolate::DartDev_Result_Run);
1228 if (should_run_user_program) {
1229 try_load_snapshots_lambda();
1230 }
1231 }
1232#endif // !defined(DART_PRECOMPILED_RUNTIME)
1233
1234 if (should_run_user_program) {
1235 if (!Dart_IsPrecompiledRuntime() && Snapshot::IsAOTSnapshot(script_name)) {
1236 Syslog::PrintErr(
1237 "%s is an AOT snapshot and should be run with 'dartaotruntime'\n",
1238 script_name);
1239 Platform::Exit(kErrorExitCode);
1240 } else {
1241 // Run the main isolate until we aren't told to restart.
1242 while (RunMainIsolate(script_name, &dart_options)) {
1243 Syslog::PrintErr("Restarting VM\n");
1244 }
1245 }
1246 }
1247
1248 // Terminate process exit-code handler.
1249 Process::TerminateExitCodeHandler();
1250
1251 error = Dart_Cleanup();
1252 if (error != NULL) {
1253 Syslog::PrintErr("VM cleanup failed: %s\n", error);
1254 free(error);
1255 }
1256 const intptr_t global_exit_code = Process::GlobalExitCode();
1257 dart::embedder::Cleanup();
1258
1259 delete app_snapshot;
1260 free(app_script_uri);
1261 if (ran_dart_dev && script_name != nullptr) {
1262 free(script_name);
1263 }
1264
1265 // Free copied argument strings if converted.
1266 if (argv_converted) {
1267 for (int i = 0; i < argc; i++) {
1268 free(argv[i]);
1269 }
1270 }
1271
1272 // Free environment if any.
1273 Options::DestroyEnvironment();
1274
1275 Platform::Exit(global_exit_code);
1276}
1277
1278} // namespace bin
1279} // namespace dart
1280
1281int main(int argc, char** argv) {
1282 dart::bin::main(argc, argv);
1283 UNREACHABLE();
1284}
1285