blob: 41939659054b65a2986647f61ff8b88548ad92b4 [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>
Ben Konyi3849b502020-07-16 19:50:57 +00008
Ben Konyi157ebfe2020-07-21 16:23:18 +00009#include <memory>
Alexander Aprelev7e373832020-07-17 04:37:48 +000010
dgrove@google.com4c0f5592011-10-05 05:20:07 +000011#include "bin/builtin.h"
Ben Konyi3c8d3b62018-03-12 20:31:09 +000012#include "bin/console.h"
Vyacheslav Egorovf1850122018-10-29 15:11:16 +000013#include "bin/crashpad.h"
Ben Konyi157ebfe2020-07-21 16:23:18 +000014#include "bin/dartdev_isolate.h"
asiva@google.com0ce82982011-11-18 18:24:04 +000015#include "bin/dartutils.h"
Siva Annamalai286dd512017-05-25 15:40:36 -070016#include "bin/dfe.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"
dgrove@google.com4c0f5592011-10-05 05:20:07 +000019#include "bin/file.h"
Vyacheslav Egorovf1850122018-10-29 15:11:16 +000020#include "bin/gzip.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"
Zachary Andersond7845c62017-09-11 18:58:39 +000023#include "bin/main_options.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"
Ben Konyi157ebfe2020-07-21 16:23:18 +000030#include "include/bin/dart_io_api.h"
31#include "include/dart_api.h"
32#include "include/dart_embedder_api.h"
33#include "include/dart_tools_api.h"
ager@google.comc4c92c42012-01-06 11:28:21 +000034#include "platform/globals.h"
P.Y. Laligand8f035202017-03-27 06:44:21 -070035#include "platform/growable_array.h"
sgjesse@google.com36a67fa2013-10-31 05:46:57 +000036#include "platform/hashmap.h"
Ryan Macnak971f4842019-04-22 20:15:43 +000037#include "platform/syslog.h"
Ivan Posva6249c2b2015-12-03 17:46:02 -080038#include "platform/text_buffer.h"
Ben Konyi65486942020-02-06 00:04:09 +000039#include "platform/utils.h"
ager@google.comc4c92c42012-01-06 11:28:21 +000040
Ryan Macnak14ec8fa2017-05-24 14:38:09 -070041extern "C" {
42extern const uint8_t kDartVmSnapshotData[];
43extern const uint8_t kDartVmSnapshotInstructions[];
44extern const uint8_t kDartCoreIsolateSnapshotData[];
45extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
46}
47
smok@google.comebbc2022013-04-25 14:22:30 +000048namespace dart {
49namespace bin {
50
asivaac4b43f2020-01-08 18:56:21 +000051// Snapshot pieces we link in a snapshot.
Ryan Macnak14ec8fa2017-05-24 14:38:09 -070052const uint8_t* vm_snapshot_data = kDartVmSnapshotData;
53const uint8_t* vm_snapshot_instructions = kDartVmSnapshotInstructions;
54const uint8_t* core_isolate_snapshot_data = kDartCoreIsolateSnapshotData;
Ryan Macnak76df24b2017-05-31 13:49:09 -070055const uint8_t* core_isolate_snapshot_instructions =
56 kDartCoreIsolateSnapshotInstructions;
dgrove@google.com4c0f5592011-10-05 05:20:07 +000057
Siva Annamalai62b12f22016-02-05 15:28:59 -080058/**
Zachary Andersond7845c62017-09-11 18:58:39 +000059 * Global state used to control and store generation of application snapshots.
Siva Annamalaiaf4d2462016-10-19 17:42:01 -070060 * An application snapshot can be generated and run using the following
61 * command
62 * dart --snapshot-kind=app-jit --snapshot=<app_snapshot_filename>
63 * <script_uri> [<script_options>]
64 * To Run the application snapshot generated above, use :
65 * dart <app_snapshot_filename> [<script_options>]
Siva Annamalai62b12f22016-02-05 15:28:59 -080066 */
Ryan Macnak26a364f2017-01-17 15:59:41 -080067static bool vm_run_app_snapshot = false;
Ryan Macnak26a364f2017-01-17 15:59:41 -080068static char* app_script_uri = NULL;
Ryan Macnakb46af1e2017-01-23 10:25:02 -080069static const uint8_t* app_isolate_snapshot_data = NULL;
70static const uint8_t* app_isolate_snapshot_instructions = NULL;
asivad1bd8872018-08-21 20:28:06 +000071static bool kernel_isolate_is_running = false;
Ryan Macnak26a364f2017-01-17 15:59:41 -080072
Ryan Macnak4d65db8a2016-10-31 15:56:25 -070073static Dart_Isolate main_isolate = NULL;
74
Siva Chandra8b405072017-06-22 10:10:42 -070075#define SAVE_ERROR_AND_EXIT(result) \
Alexander Aprelevd33e51d2020-06-25 03:36:41 +000076 *error = Utils::StrDup(Dart_GetError(result)); \
Siva Chandra8b405072017-06-22 10:10:42 -070077 if (Dart_IsCompilationError(result)) { \
78 *exit_code = kCompilationErrorExitCode; \
79 } else if (Dart_IsApiError(result)) { \
80 *exit_code = kApiErrorExitCode; \
81 } else { \
82 *exit_code = kErrorExitCode; \
83 } \
84 Dart_ExitScope(); \
85 Dart_ShutdownIsolate(); \
86 return NULL;
87
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +000088#define CHECK_RESULT(result) \
89 if (Dart_IsError(result)) { \
Siva Chandra8b405072017-06-22 10:10:42 -070090 SAVE_ERROR_AND_EXIT(result); \
91 }
92
Siva Chandra8b405072017-06-22 10:10:42 -070093#define CHECK_RESULT_CLEANUP(result, cleanup) \
94 if (Dart_IsError(result)) { \
95 delete (cleanup); \
96 SAVE_ERROR_AND_EXIT(result); \
Zachary Anderson479a97b2016-11-04 12:30:56 -070097 }
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +000098
Zachary Andersonf06bf4c2018-02-07 05:08:45 +000099static void WriteDepsFile(Dart_Isolate isolate) {
Zach Anderson00e31092018-07-31 17:09:31 +0000100 if (Options::depfile() == NULL) {
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000101 return;
102 }
Samir Jindela8460982019-12-10 12:26:05 +0000103 File* file = File::Open(NULL, Options::depfile(), File::kWriteTruncate);
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000104 if (file == NULL) {
105 ErrorExit(kErrorExitCode, "Error: Unable to open snapshot depfile: %s\n\n",
Zach Anderson00e31092018-07-31 17:09:31 +0000106 Options::depfile());
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000107 }
108 bool success = true;
Daco Harkes35223582021-05-21 11:52:02 +0000109 if (Options::depfile_output_filename() != NULL) {
Zach Anderson00e31092018-07-31 17:09:31 +0000110 success &= file->Print("%s: ", Options::depfile_output_filename());
Daco Harkes35223582021-05-21 11:52:02 +0000111 } else {
112 success &= file->Print("%s: ", Options::snapshot_filename());
Zach Anderson00e31092018-07-31 17:09:31 +0000113 }
asiva355c73d2018-09-24 20:38:08 +0000114 if (kernel_isolate_is_running) {
115 Dart_KernelCompilationResult result = Dart_KernelListDependencies();
116 if (result.status != Dart_KernelCompilationStatus_Ok) {
117 ErrorExit(
118 kErrorExitCode,
119 "Error: Failed to fetch dependencies from kernel service: %s\n\n",
120 result.error);
Ryan Macnak26c7ab12018-06-12 22:29:33 +0000121 }
asiva355c73d2018-09-24 20:38:08 +0000122 success &= file->WriteFully(result.kernel, result.kernel_size);
123 free(result.kernel);
Ryan Macnak26c7ab12018-06-12 22:29:33 +0000124 }
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000125 success &= file->Print("\n");
126 if (!success) {
127 ErrorExit(kErrorExitCode, "Error: Unable to write snapshot depfile: %s\n\n",
Zach Anderson00e31092018-07-31 17:09:31 +0000128 Options::depfile());
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000129 }
130 file->Release();
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000131}
132
Zach Anderson00e31092018-07-31 17:09:31 +0000133static void OnExitHook(int64_t exit_code) {
Ryan Macnak6500f6e2017-02-13 11:17:31 -0800134 if (Dart_CurrentIsolate() != main_isolate) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000135 Syslog::PrintErr(
Ryan Macnak6500f6e2017-02-13 11:17:31 -0800136 "A snapshot was requested, but a secondary isolate "
137 "performed a hard exit (%" Pd64 ").\n",
138 exit_code);
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800139 Platform::Exit(kErrorExitCode);
140 }
Ryan Macnak6500f6e2017-02-13 11:17:31 -0800141 if (exit_code == 0) {
Zach Anderson00e31092018-07-31 17:09:31 +0000142 if (Options::gen_snapshot_kind() == kAppJIT) {
143 Snapshot::GenerateAppJIT(Options::snapshot_filename());
144 }
Zachary Andersonf06bf4c2018-02-07 05:08:45 +0000145 WriteDepsFile(main_isolate);
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800146 }
Ryan Macnak9eb216a2017-01-31 09:47:51 -0800147}
148
Alexander Aprelev04259972019-07-08 23:49:05 +0000149static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
150 IsolateData* isolate_data,
Siva Annamalaid46a6962020-06-20 08:02:53 +0000151 bool is_isolate_group_start,
152 const char** resolved_packages_config) {
Alexander Aprelev04259972019-07-08 23:49:05 +0000153 auto isolate_group_data = isolate_data->isolate_group_data();
Siva Annamalaid46a6962020-06-20 08:02:53 +0000154 const auto packages_file = isolate_data->packages_file();
Alexander Aprelev04259972019-07-08 23:49:05 +0000155 const auto script_uri = isolate_group_data->script_url;
156
157 Dart_Handle result;
158
Alexander Aprelev04259972019-07-08 23:49:05 +0000159 // Prepare builtin and other core libraries for use to resolve URIs.
160 // Set up various closures, e.g: printing, timers etc.
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000161 // Set up package configuration for URI resolution.
Alexander Aprelev04259972019-07-08 23:49:05 +0000162 result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
163 if (Dart_IsError(result)) return result;
164
Siva Annamalaid46a6962020-06-20 08:02:53 +0000165 // Setup packages config if specified.
166 result = DartUtils::SetupPackageConfig(packages_file);
167 if (Dart_IsError(result)) return result;
168 if (!Dart_IsNull(result) && resolved_packages_config != nullptr) {
169 result = Dart_StringToCString(result, resolved_packages_config);
170 if (Dart_IsError(result)) return result;
171 ASSERT(*resolved_packages_config != nullptr);
172#if !defined(DART_PRECOMPILED_RUNTIME)
173 if (is_isolate_group_start) {
174 isolate_group_data->set_resolved_packages_config(
175 *resolved_packages_config);
176 } else {
177 ASSERT(strcmp(isolate_group_data->resolved_packages_config(),
178 *resolved_packages_config) == 0);
179 }
180#endif
181 }
182
Alexander Aprelev04259972019-07-08 23:49:05 +0000183 result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
184 if (Dart_IsError(result)) return result;
185
186 // Setup the native resolver as the snapshot does not carry it.
187 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
188 Builtin::SetNativeResolver(Builtin::kIOLibrary);
189 Builtin::SetNativeResolver(Builtin::kCLILibrary);
190 VmService::SetNativeResolver();
191
192 const char* namespc =
193 Dart_IsKernelIsolate(isolate) ? NULL : Options::namespc();
194 result =
195 DartUtils::SetupIOLibrary(namespc, script_uri, Options::exit_disabled());
196 if (Dart_IsError(result)) return result;
197
198 return Dart_Null();
199}
200
201static bool OnIsolateInitialize(void** child_callback_data, char** error) {
202 Dart_Isolate isolate = Dart_CurrentIsolate();
203 ASSERT(isolate != nullptr);
204
205 auto isolate_group_data =
206 reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
207
208 auto isolate_data = new IsolateData(isolate_group_data);
209 *child_callback_data = isolate_data;
210
211 Dart_EnterScope();
212 const auto script_uri = isolate_group_data->script_url;
213 const bool isolate_run_app_snapshot =
214 isolate_group_data->RunFromAppSnapshot();
215 Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
Siva Annamalaid46a6962020-06-20 08:02:53 +0000216 /*group_start=*/false,
217 /*resolved_packages_config=*/nullptr);
Alexander Aprelev04259972019-07-08 23:49:05 +0000218 if (Dart_IsError(result)) goto failed;
219
Siva Annamalaid46a6962020-06-20 08:02:53 +0000220 if (isolate_run_app_snapshot) {
Ryan Macnak9cb5d8e52020-08-04 19:00:18 +0000221 result = Loader::InitForSnapshot(script_uri, isolate_data);
222 if (Dart_IsError(result)) goto failed;
Siva Annamalaid46a6962020-06-20 08:02:53 +0000223 } else {
224 result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
225 if (Dart_IsError(result)) return result != nullptr;
226
227 if (isolate_group_data->kernel_buffer().get() != nullptr) {
228 // Various core-library parts will send requests to the Loader to resolve
229 // relative URIs and perform other related tasks. We need Loader to be
230 // initialized for this to work because loading from Kernel binary
231 // bypasses normal source code loading paths that initialize it.
232 const char* resolved_script_uri = NULL;
233 result = Dart_StringToCString(result, &resolved_script_uri);
234 if (Dart_IsError(result)) goto failed;
235 result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
236 if (Dart_IsError(result)) goto failed;
237 }
238 }
Alexander Aprelev04259972019-07-08 23:49:05 +0000239
Alexander Aprelev04259972019-07-08 23:49:05 +0000240 Dart_ExitScope();
Martin Kustermann42ac7622020-11-12 08:49:38 +0000241 return true;
Alexander Aprelev04259972019-07-08 23:49:05 +0000242
243failed:
Alexander Aprelevd33e51d2020-06-25 03:36:41 +0000244 *error = Utils::StrDup(Dart_GetError(result));
Alexander Aprelev04259972019-07-08 23:49:05 +0000245 Dart_ExitScope();
246 return false;
247}
248
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700249static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
250 bool is_main_isolate,
251 const char* script_uri,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700252 const char* packages_config,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700253 bool isolate_run_app_snapshot,
asivaee6351a2018-05-01 22:57:35 +0000254 Dart_IsolateFlags* flags,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700255 char** error,
256 int* exit_code) {
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000257 Dart_EnterScope();
258
Alexander Aprelevf66964c2019-07-23 20:03:42 +0000259 // Set up the library tag handler for the isolate group shared by all
260 // isolates in the group.
261 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
262 CHECK_RESULT(result);
Ryan Macnakc5a94db2020-07-17 19:29:47 +0000263 result = Dart_SetDeferredLoadHandler(Loader::DeferredLoadHandler);
264 CHECK_RESULT(result);
Alexander Aprelevf66964c2019-07-23 20:03:42 +0000265
Alexander Aprelev04259972019-07-08 23:49:05 +0000266 auto isolate_data = reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100267
Siva Annamalaid46a6962020-06-20 08:02:53 +0000268 const char* resolved_packages_config = nullptr;
Alexander Aprelevf66964c2019-07-23 20:03:42 +0000269 result = SetupCoreLibraries(isolate, isolate_data,
Siva Annamalaid46a6962020-06-20 08:02:53 +0000270 /*is_isolate_group_start=*/true,
271 &resolved_packages_config);
asivaee6351a2018-05-01 22:57:35 +0000272 CHECK_RESULT(result);
273
Siva Annamalai53cf85a2017-07-27 10:06:52 -0700274#if !defined(DART_PRECOMPILED_RUNTIME)
Alexander Aprelev04259972019-07-08 23:49:05 +0000275 auto isolate_group_data = isolate_data->isolate_group_data();
276 const uint8_t* kernel_buffer = isolate_group_data->kernel_buffer().get();
277 intptr_t kernel_buffer_size = isolate_group_data->kernel_buffer_size();
asiva355c73d2018-09-24 20:38:08 +0000278 if (!isolate_run_app_snapshot && kernel_buffer == NULL &&
279 !Dart_IsKernelIsolate(isolate)) {
asivaee6351a2018-05-01 22:57:35 +0000280 if (!dfe.CanUseDartFrontend()) {
281 const char* format = "Dart frontend unavailable to compile script %s.";
282 intptr_t len = snprintf(NULL, 0, format, script_uri) + 1;
283 *error = reinterpret_cast<char*>(malloc(len));
284 ASSERT(error != NULL);
285 snprintf(*error, len, format, script_uri);
286 *exit_code = kErrorExitCode;
287 Dart_ExitScope();
288 Dart_ShutdownIsolate();
289 return NULL;
290 }
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000291 uint8_t* application_kernel_buffer = NULL;
292 intptr_t application_kernel_buffer_size = 0;
Johnni Winther55b34a42021-01-21 21:18:32 +0000293 // Only pass snapshot = true when generating an AppJIT snapshot to avoid
294 // duplicate null-safety info messages from the frontend when generating
295 // a kernel snapshot (this flag is instead set in
296 // Snapshot::GenerateKernel()).
297 const bool snapshot = Options::gen_snapshot_kind() == kAppJIT;
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000298 dfe.CompileAndReadScript(script_uri, &application_kernel_buffer,
299 &application_kernel_buffer_size, error, exit_code,
Johnni Winther55b34a42021-01-21 21:18:32 +0000300 resolved_packages_config, snapshot);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000301 if (application_kernel_buffer == NULL) {
asivaee6351a2018-05-01 22:57:35 +0000302 Dart_ExitScope();
303 Dart_ShutdownIsolate();
304 return NULL;
305 }
Alexander Aprelev04259972019-07-08 23:49:05 +0000306 isolate_group_data->SetKernelBufferNewlyOwned(
307 application_kernel_buffer, application_kernel_buffer_size);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000308 kernel_buffer = application_kernel_buffer;
309 kernel_buffer_size = application_kernel_buffer_size;
asivaee6351a2018-05-01 22:57:35 +0000310 }
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000311 if (kernel_buffer != NULL) {
Siva Annamalaid46a6962020-06-20 08:02:53 +0000312 Dart_Handle uri = Dart_NewStringFromCString(script_uri);
313 CHECK_RESULT(uri);
314 Dart_Handle resolved_script_uri = DartUtils::ResolveScript(uri);
315 CHECK_RESULT(resolved_script_uri);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000316 result = Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
Siva Chandrab47a5b22018-01-24 01:40:37 +0000317 CHECK_RESULT(result);
Vyacheslav Egorov23fd1a12016-11-16 13:56:20 +0100318 }
Siva Annamalai53cf85a2017-07-27 10:06:52 -0700319#endif // !defined(DART_PRECOMPILED_RUNTIME)
320
Ryan Macnak26a364f2017-01-17 15:59:41 -0800321 if (isolate_run_app_snapshot) {
Ryan Macnak9cb5d8e52020-08-04 19:00:18 +0000322 Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data);
323 CHECK_RESULT(result);
Siva Annamalaid46a6962020-06-20 08:02:53 +0000324#if !defined(DART_PRECOMPILED_RUNTIME)
Ryan Macnak26a364f2017-01-17 15:59:41 -0800325 if (is_main_isolate) {
326 // Find the canonical uri of the app snapshot. We'll use this to decide if
327 // other isolates should use the app snapshot or the core snapshot.
Siva Annamalaid46a6962020-06-20 08:02:53 +0000328 const char* resolved_script_uri = NULL;
329 result = Dart_StringToCString(
330 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri)),
331 &resolved_script_uri);
Ryan Macnak26a364f2017-01-17 15:59:41 -0800332 CHECK_RESULT(result);
333 ASSERT(app_script_uri == NULL);
Alexander Aprelevd33e51d2020-06-25 03:36:41 +0000334 app_script_uri = Utils::StrDup(resolved_script_uri);
Ryan Macnak26a364f2017-01-17 15:59:41 -0800335 }
asiva03777db2020-06-20 05:50:49 +0000336#endif // !defined(DART_PRECOMPILED_RUNTIME)
Siva Annamalaid46a6962020-06-20 08:02:53 +0000337 } else {
338#if !defined(DART_PRECOMPILED_RUNTIME)
339 // Load the specified application script into the newly created isolate.
340 Dart_Handle uri =
341 DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
342 CHECK_RESULT(uri);
343 if (kernel_buffer != NULL) {
344 // relative URIs and perform other related tasks. We need Loader to be
345 // initialized for this to work because loading from Kernel binary
346 // bypasses normal source code loading paths that initialize it.
347 const char* resolved_script_uri = NULL;
348 result = Dart_StringToCString(uri, &resolved_script_uri);
349 CHECK_RESULT(result);
350 result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
351 CHECK_RESULT(result);
352 }
353 Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
354 Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
355 NULL, NULL);
356#else
357 UNREACHABLE();
358#endif // !defined(DART_PRECOMPILED_RUNTIME)
359 }
John McCutchan1ff71442015-08-18 15:18:02 -0700360
Ryan Macnakbe9bb432021-08-30 20:26:57 +0000361 if (Options::gen_snapshot_kind() == kAppJIT && !isolate_run_app_snapshot) {
Ryan Macnakd2536422019-02-21 22:39:39 +0000362 // If we sort, we must do it for all isolates, not just the main isolate,
363 // otherwise isolates related by spawnFunction will disagree on CIDs and
Ryan Macnakbe9bb432021-08-30 20:26:57 +0000364 // cannot correctly send each other messages. If we run from an app
365 // snapshot, things are already sorted, and other isolate created by
366 // spawnFunction will also load from the same snapshot. Sorting such isolate
367 // is counter-productive because it invalidates their code.
368 // After we switch to always using isolate groups, this be changed to
369 // `generating-app-jit && is_main_isolate`.
Ryan Macnakd2536422019-02-21 22:39:39 +0000370 result = Dart_SortClasses();
371 CHECK_RESULT(result);
372 }
373
Ben Konyi157ebfe2020-07-21 16:23:18 +0000374 // Disable pausing the DartDev isolate on start and exit.
375 const char* isolate_name = nullptr;
376 result = Dart_StringToCString(Dart_DebugName(), &isolate_name);
377 CHECK_RESULT(result);
Ben Konyi9bac3272020-08-13 22:04:24 +0000378#if !defined(DART_PRECOMPILED_RUNTIME)
379 if (strstr(isolate_name, DART_DEV_ISOLATE_NAME) != nullptr) {
Ben Konyi157ebfe2020-07-21 16:23:18 +0000380 Dart_SetShouldPauseOnStart(false);
381 Dart_SetShouldPauseOnExit(false);
382 }
Ben Konyi9bac3272020-08-13 22:04:24 +0000383#endif // !defined(DART_PRECOMPILED_RUNTIME)
Ben Konyi157ebfe2020-07-21 16:23:18 +0000384
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000385 // Make the isolate runnable so that it is ready to handle messages.
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000386 Dart_ExitScope();
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000387 Dart_ExitIsolate();
Ryan Macnak607f4f52018-05-01 20:54:38 +0000388 *error = Dart_IsolateMakeRunnable(isolate);
389 if (*error != NULL) {
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000390 Dart_EnterIsolate(isolate);
391 Dart_ShutdownIsolate();
392 return NULL;
393 }
394
iposva@google.com0d0fcbe2013-04-09 17:51:24 +0000395 return isolate;
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000396}
397
asiva1aaebed2018-02-28 01:15:47 +0000398#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700399// Returns newly created Kernel Isolate on success, NULL on failure.
400// For now we only support the kernel isolate coming up from an
Siva Chandra4b73d122018-01-12 20:40:41 +0000401// application snapshot or from a .dill file.
402static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700403 const char* packages_config,
404 Dart_IsolateFlags* flags,
405 char** error,
406 int* exit_code) {
asiva1f5f1972018-08-20 21:32:21 +0000407 // Do not start a kernel isolate if we are doing a training run
408 // to create an app JIT snapshot and a kernel file is specified
409 // as the application to run.
410 if (Options::gen_snapshot_kind() == kAppJIT) {
411 const uint8_t* kernel_buffer = NULL;
412 intptr_t kernel_buffer_size = 0;
413 dfe.application_kernel_buffer(&kernel_buffer, &kernel_buffer_size);
414 if (kernel_buffer_size != 0) {
415 return NULL;
416 }
Vyacheslav Egorov03203762018-08-19 19:58:32 +0000417 }
asiva1f5f1972018-08-20 21:32:21 +0000418 // Create and Start the kernel isolate.
419 const char* kernel_snapshot_uri = dfe.frontend_filename();
Siva Chandra4b73d122018-01-12 20:40:41 +0000420 const char* uri =
421 kernel_snapshot_uri != NULL ? kernel_snapshot_uri : script_uri;
422
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700423 if (packages_config == NULL) {
Zachary Andersond7845c62017-09-11 18:58:39 +0000424 packages_config = Options::packages_file();
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700425 }
426
asivacd3dded2018-09-07 21:22:13 +0000427 Dart_Isolate isolate = NULL;
Alexander Aprelev04259972019-07-08 23:49:05 +0000428 IsolateGroupData* isolate_group_data = nullptr;
429 IsolateData* isolate_data = nullptr;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700430 bool isolate_run_app_snapshot = false;
asivad1bd8872018-08-21 20:28:06 +0000431 AppSnapshot* app_snapshot = NULL;
432 // Kernel isolate uses an app snapshot or uses the dill file.
433 if ((kernel_snapshot_uri != NULL) &&
Ben Konyi4de9e802021-10-27 16:34:00 +0000434 (app_snapshot = Snapshot::TryReadAppSnapshot(
435 kernel_snapshot_uri, /*force_load_elf_from_memory=*/false,
436 /*decode_uri=*/false)) != nullptr) {
asivad1bd8872018-08-21 20:28:06 +0000437 const uint8_t* isolate_snapshot_data = NULL;
438 const uint8_t* isolate_snapshot_instructions = NULL;
439 const uint8_t* ignore_vm_snapshot_data;
440 const uint8_t* ignore_vm_snapshot_instructions;
441 isolate_run_app_snapshot = true;
442 app_snapshot->SetBuffers(
443 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
444 &isolate_snapshot_data, &isolate_snapshot_instructions);
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000445 isolate_group_data = new IsolateGroupData(
446 uri, packages_config, app_snapshot, isolate_run_app_snapshot);
Alexander Aprelev04259972019-07-08 23:49:05 +0000447 isolate_data = new IsolateData(isolate_group_data);
448 isolate = Dart_CreateIsolateGroup(
Ben Konyiac2c9342019-03-28 16:39:50 +0000449 DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
Ryan Macnak6a65ea92019-10-22 19:02:26 +0000450 isolate_snapshot_data, isolate_snapshot_instructions, flags,
Alexander Aprelev04259972019-07-08 23:49:05 +0000451 isolate_group_data, isolate_data, error);
asivacd3dded2018-09-07 21:22:13 +0000452 }
453 if (isolate == NULL) {
Ryan Macnakc8bda472018-10-08 22:43:09 +0000454 // Clear error from app snapshot and re-trying from kernel file.
455 free(*error);
456 *error = NULL;
Martin Kustermannb2171f12019-06-26 16:04:27 +0000457 delete isolate_data;
Alexander Aprelev04259972019-07-08 23:49:05 +0000458 delete isolate_group_data;
Ryan Macnakc8bda472018-10-08 22:43:09 +0000459
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000460 const uint8_t* kernel_service_buffer = NULL;
461 intptr_t kernel_service_buffer_size = 0;
462 dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size);
463 ASSERT(kernel_service_buffer != NULL);
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000464 isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr,
465 isolate_run_app_snapshot);
Alexander Aprelev04259972019-07-08 23:49:05 +0000466 isolate_group_data->SetKernelBufferUnowned(
Alexander Aprelev7d147852018-12-14 23:45:57 +0000467 const_cast<uint8_t*>(kernel_service_buffer),
468 kernel_service_buffer_size);
Alexander Aprelev04259972019-07-08 23:49:05 +0000469 isolate_data = new IsolateData(isolate_group_data);
470 isolate = Dart_CreateIsolateGroupFromKernel(
Ben Konyiac2c9342019-03-28 16:39:50 +0000471 DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
Alexander Aprelev04259972019-07-08 23:49:05 +0000472 kernel_service_buffer, kernel_service_buffer_size, flags,
473 isolate_group_data, isolate_data, error);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700474 }
475
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700476 if (isolate == NULL) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000477 Syslog::PrintErr("%s\n", *error);
Martin Kustermannb2171f12019-06-26 16:04:27 +0000478 delete isolate_data;
Alexander Aprelev04259972019-07-08 23:49:05 +0000479 delete isolate_group_data;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700480 return NULL;
481 }
asivad1bd8872018-08-21 20:28:06 +0000482 kernel_isolate_is_running = true;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700483
Alexander Aprelev04259972019-07-08 23:49:05 +0000484 return IsolateSetupHelper(isolate, false, uri, packages_config,
asivae70a7aa2018-10-10 23:19:24 +0000485 isolate_run_app_snapshot, flags, error, exit_code);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700486}
asiva1aaebed2018-02-28 01:15:47 +0000487#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700488
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700489// Returns newly created Service Isolate on success, NULL on failure.
490// For now we only support the service isolate coming up from sources
491// which are compiled by the VM parser.
492static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700493 const char* packages_config,
494 Dart_IsolateFlags* flags,
495 char** error,
496 int* exit_code) {
asiva8e4421a2019-12-27 19:46:15 +0000497#if !defined(PRODUCT)
Alexander Markov6b4fe2f2020-07-01 20:22:24 +0000498 ASSERT(script_uri != nullptr);
499 Dart_Isolate isolate = nullptr;
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000500 auto isolate_group_data =
501 new IsolateGroupData(script_uri, packages_config, nullptr, false);
Alexander Markov6b4fe2f2020-07-01 20:22:24 +0000502 ASSERT(flags != nullptr);
asiva76470ac2018-09-27 00:55:07 +0000503
Siva Chandra8b405072017-06-22 10:10:42 -0700504#if defined(DART_PRECOMPILED_RUNTIME)
asiva76470ac2018-09-27 00:55:07 +0000505 // AOT: All isolates start from the app snapshot.
506 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
507 const uint8_t* isolate_snapshot_instructions =
508 app_isolate_snapshot_instructions;
Alexander Markov6b4fe2f2020-07-01 20:22:24 +0000509 flags->null_safety =
510 Dart_DetectNullSafety(nullptr, nullptr, nullptr, isolate_snapshot_data,
511 isolate_snapshot_instructions, nullptr, -1);
Alexander Aprelev04259972019-07-08 23:49:05 +0000512 isolate = Dart_CreateIsolateGroup(
Ben Konyiac2c9342019-03-28 16:39:50 +0000513 script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
Ryan Macnak6a65ea92019-10-22 19:02:26 +0000514 isolate_snapshot_instructions, flags, isolate_group_data,
Alexander Aprelev04259972019-07-08 23:49:05 +0000515 /*isolate_data=*/nullptr, error);
Siva Chandra8b405072017-06-22 10:10:42 -0700516#else
asiva76470ac2018-09-27 00:55:07 +0000517 // JIT: Service isolate uses the core libraries snapshot.
518
asivae70a7aa2018-10-10 23:19:24 +0000519 // Set flag to load and retain the vmservice library.
Siva Chandra8d7bc502018-01-11 11:12:04 -0800520 flags->load_vmservice_library = true;
Alexander Markov74792f42018-10-22 20:51:48 +0000521 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
522 const uint8_t* isolate_snapshot_instructions =
523 core_isolate_snapshot_instructions;
Alexander Aprelev04259972019-07-08 23:49:05 +0000524 isolate = Dart_CreateIsolateGroup(
Ben Konyiac2c9342019-03-28 16:39:50 +0000525 script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
Ryan Macnak6a65ea92019-10-22 19:02:26 +0000526 isolate_snapshot_instructions, flags, isolate_group_data,
Alexander Aprelev04259972019-07-08 23:49:05 +0000527 /*isolate_data=*/nullptr, error);
Siva Chandra8b405072017-06-22 10:10:42 -0700528#endif // !defined(DART_PRECOMPILED_RUNTIME)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700529 if (isolate == NULL) {
Alexander Aprelev04259972019-07-08 23:49:05 +0000530 delete isolate_group_data;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700531 return NULL;
532 }
533
534 Dart_EnterScope();
535
536 Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
537 CHECK_RESULT(result);
Ryan Macnakc5a94db2020-07-17 19:29:47 +0000538 result = Dart_SetDeferredLoadHandler(Loader::DeferredLoadHandler);
539 CHECK_RESULT(result);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700540
Ben Konyif0d88cc2020-09-03 15:20:14 +0000541 int vm_service_server_port = INVALID_VM_SERVICE_SERVER_PORT;
Ben Konyi123950f2021-09-16 20:31:45 +0000542 if (Options::disable_dart_dev() || Options::disable_dds()) {
Ben Konyif0d88cc2020-09-03 15:20:14 +0000543 vm_service_server_port = Options::vm_service_server_port();
544 } else if (Options::vm_service_server_port() !=
545 INVALID_VM_SERVICE_SERVER_PORT) {
546 vm_service_server_port = 0;
547 }
548
Ben Konyib99466d2021-05-11 17:55:26 +0000549 // We do not want to wait for DDS to advertise availability of VM service in
550 // the following scenarios:
551 // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is
552 // enabled.
Ben Konyi123950f2021-09-16 20:31:45 +0000553 // - DDS is disabled.
Ben Konyib99466d2021-05-11 17:55:26 +0000554 // TODO(bkonyi): do we want to tie DevTools / DDS to the CLI in the long run?
Ben Konyi123950f2021-09-16 20:31:45 +0000555 bool wait_for_dds_to_advertise_service =
556 !(Options::disable_dart_dev() || Options::disable_dds());
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700557 // Load embedder specific bits and return.
Ben Konyic3da0252020-09-16 18:38:28 +0000558 if (!VmService::Setup(
Ben Konyi123950f2021-09-16 20:31:45 +0000559 !wait_for_dds_to_advertise_service ? Options::vm_service_server_ip()
560 : DEFAULT_VM_SERVICE_SERVER_IP,
Ben Konyic3da0252020-09-16 18:38:28 +0000561 vm_service_server_port, Options::vm_service_dev_mode(),
562 Options::vm_service_auth_disabled(),
563 Options::vm_write_service_info_filename(), Options::trace_loading(),
564 Options::deterministic(), Options::enable_service_port_fallback(),
Ben Konyi4faadf12021-03-24 23:59:23 +0000565 wait_for_dds_to_advertise_service)) {
Alexander Aprelevd33e51d2020-06-25 03:36:41 +0000566 *error = Utils::StrDup(VmService::GetErrorMessage());
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700567 return NULL;
568 }
Zachary Andersond7845c62017-09-11 18:58:39 +0000569 if (Options::compile_all()) {
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700570 result = Dart_CompileAll();
571 CHECK_RESULT(result);
572 }
Zach Anderson27c79f92018-09-06 02:23:21 +0000573 result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700574 CHECK_RESULT(result);
575 Dart_ExitScope();
576 Dart_ExitIsolate();
577 return isolate;
asiva8e4421a2019-12-27 19:46:15 +0000578#else // !defined(PRODUCT)
579 return NULL;
580#endif // !defined(PRODUCT)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700581}
582
Ben Konyi9bac3272020-08-13 22:04:24 +0000583#if !defined(DART_PRECOMPILED_RUNTIME)
584
585static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
586 const char* packages_config,
587 Dart_IsolateFlags* flags,
588 char** error,
589 int* exit_code) {
590 int64_t start = Dart_TimelineGetMicros();
591
592 auto dartdev_path = DartDevIsolate::TryResolveDartDevSnapshotPath();
Ben Konyi9bac3272020-08-13 22:04:24 +0000593
Ben Konyic42c76f2021-01-11 19:41:50 +0000594 Dart_Isolate isolate = nullptr;
Ben Konyi9bac3272020-08-13 22:04:24 +0000595 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
596 const uint8_t* isolate_snapshot_instructions =
597 core_isolate_snapshot_instructions;
Ben Konyic42c76f2021-01-11 19:41:50 +0000598 IsolateGroupData* isolate_group_data = nullptr;
599 IsolateData* isolate_data = nullptr;
Ben Konyi9bac3272020-08-13 22:04:24 +0000600
Ben Konyifd259d42021-01-11 23:25:28 +0000601 if (error != nullptr) {
602 *error = nullptr;
603 }
604 AppSnapshot* app_snapshot = nullptr;
Ben Konyic42c76f2021-01-11 19:41:50 +0000605 bool isolate_run_app_snapshot = true;
606 if (dartdev_path.get() != nullptr &&
Ben Konyi4de9e802021-10-27 16:34:00 +0000607 (app_snapshot = Snapshot::TryReadAppSnapshot(
608 dartdev_path.get(), /*force_load_elf_from_memory=*/false,
609 /*decode_uri=*/false)) != nullptr) {
Ben Konyic42c76f2021-01-11 19:41:50 +0000610 const uint8_t* isolate_snapshot_data = NULL;
611 const uint8_t* isolate_snapshot_instructions = NULL;
612 const uint8_t* ignore_vm_snapshot_data;
613 const uint8_t* ignore_vm_snapshot_instructions;
614 app_snapshot->SetBuffers(
615 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
616 &isolate_snapshot_data, &isolate_snapshot_instructions);
617 isolate_group_data =
Ben Konyi4de9e802021-10-27 16:34:00 +0000618 new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config,
619 app_snapshot, isolate_run_app_snapshot);
Ben Konyic42c76f2021-01-11 19:41:50 +0000620 isolate_data = new IsolateData(isolate_group_data);
621 isolate = Dart_CreateIsolateGroup(
622 DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
623 isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
624 error);
625 }
Ben Konyi9bac3272020-08-13 22:04:24 +0000626
Ben Konyic42c76f2021-01-11 19:41:50 +0000627 if (isolate == nullptr) {
628 isolate_run_app_snapshot = false;
629 dartdev_path = DartDevIsolate::TryResolveDartDevKernelPath();
630 // Clear error from app snapshot and retry from kernel.
Ben Konyicbc46012021-01-12 18:53:05 +0000631 if (error != nullptr && *error != nullptr) {
Ben Konyifd259d42021-01-11 23:25:28 +0000632 free(*error);
633 *error = nullptr;
634 }
Ben Konyic42c76f2021-01-11 19:41:50 +0000635
636 if (app_snapshot != nullptr) {
637 delete app_snapshot;
638 }
639
640 if (dartdev_path.get() != nullptr) {
641 isolate_group_data =
642 new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
643 isolate_run_app_snapshot);
644 uint8_t* application_kernel_buffer = NULL;
645 intptr_t application_kernel_buffer_size = 0;
646 dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
Ben Konyi4de9e802021-10-27 16:34:00 +0000647 &application_kernel_buffer_size, /*decode_uri=*/false);
Ben Konyic42c76f2021-01-11 19:41:50 +0000648 isolate_group_data->SetKernelBufferNewlyOwned(
649 application_kernel_buffer, application_kernel_buffer_size);
650
651 isolate_data = new IsolateData(isolate_group_data);
652 isolate = Dart_CreateIsolateGroup(
653 DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
654 isolate_snapshot_instructions, flags, isolate_group_data,
655 isolate_data, error);
656 }
657 }
Ben Konyi9bac3272020-08-13 22:04:24 +0000658
659 Dart_Isolate created_isolate = nullptr;
660 if (isolate == nullptr) {
Ben Konyic42c76f2021-01-11 19:41:50 +0000661 Syslog::PrintErr("Failed to start the Dart CLI isolate\n");
Ben Konyi9bac3272020-08-13 22:04:24 +0000662 delete isolate_data;
663 delete isolate_group_data;
Ben Konyic42c76f2021-01-11 19:41:50 +0000664 return nullptr;
Ben Konyi9bac3272020-08-13 22:04:24 +0000665 } else {
666 created_isolate = IsolateSetupHelper(
667 isolate, false, DART_DEV_ISOLATE_NAME, packages_config,
Ben Konyic42c76f2021-01-11 19:41:50 +0000668 isolate_run_app_snapshot, flags, error, exit_code);
Ben Konyi9bac3272020-08-13 22:04:24 +0000669 }
670 int64_t end = Dart_TimelineGetMicros();
671 Dart_TimelineEvent("CreateAndSetupDartDevIsolate", start, end,
672 Dart_Timeline_Event_Duration, 0, NULL, NULL);
673 return created_isolate;
674}
675
676#endif // !defined(DART_PRECOMPILED_RUNTIME)
677
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700678// Returns newly created Isolate on success, NULL on failure.
Alexander Aprelev04259972019-07-08 23:49:05 +0000679static Dart_Isolate CreateIsolateGroupAndSetupHelper(
680 bool is_main_isolate,
681 const char* script_uri,
682 const char* name,
Alexander Aprelev04259972019-07-08 23:49:05 +0000683 const char* packages_config,
684 Dart_IsolateFlags* flags,
685 void* callback_data,
686 char** error,
687 int* exit_code) {
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000688 int64_t start = Dart_TimelineGetMicros();
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700689 ASSERT(script_uri != NULL);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000690 uint8_t* kernel_buffer = NULL;
Alexander Aprelev7d147852018-12-14 23:45:57 +0000691 std::shared_ptr<uint8_t> parent_kernel_buffer;
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000692 intptr_t kernel_buffer_size = 0;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700693 AppSnapshot* app_snapshot = NULL;
694
695#if defined(DART_PRECOMPILED_RUNTIME)
696 // AOT: All isolates start from the app snapshot.
697 bool isolate_run_app_snapshot = true;
698 const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
699 const uint8_t* isolate_snapshot_instructions =
700 app_isolate_snapshot_instructions;
asivaa782dd82020-06-11 01:22:35 +0000701 flags->null_safety =
702 Dart_DetectNullSafety(nullptr, nullptr, nullptr, isolate_snapshot_data,
703 isolate_snapshot_instructions, nullptr, -1);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700704#else
705 // JIT: Main isolate starts from the app snapshot, if any. Other isolates
706 // use the core libraries snapshot.
707 bool isolate_run_app_snapshot = false;
708 const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
709 const uint8_t* isolate_snapshot_instructions =
710 core_isolate_snapshot_instructions;
711 if ((app_isolate_snapshot_data != NULL) &&
712 (is_main_isolate || ((app_script_uri != NULL) &&
713 (strcmp(script_uri, app_script_uri) == 0)))) {
714 isolate_run_app_snapshot = true;
715 isolate_snapshot_data = app_isolate_snapshot_data;
716 isolate_snapshot_instructions = app_isolate_snapshot_instructions;
717 } else if (!is_main_isolate) {
718 app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
719 if (app_snapshot != NULL) {
720 isolate_run_app_snapshot = true;
721 const uint8_t* ignore_vm_snapshot_data;
722 const uint8_t* ignore_vm_snapshot_instructions;
723 app_snapshot->SetBuffers(
724 &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
725 &isolate_snapshot_data, &isolate_snapshot_instructions);
726 }
727 }
Alexander Aprelev7d147852018-12-14 23:45:57 +0000728
Martin Kustermanna64b06e2019-09-05 21:41:42 +0000729 if (flags->copy_parent_code && callback_data != nullptr) {
Martin Kustermann68e805f2019-08-23 15:15:58 +0000730 auto parent_isolate_group_data =
731 reinterpret_cast<IsolateData*>(callback_data)->isolate_group_data();
732 parent_kernel_buffer = parent_isolate_group_data->kernel_buffer();
Alexander Aprelev7d147852018-12-14 23:45:57 +0000733 kernel_buffer = parent_kernel_buffer.get();
Martin Kustermann68e805f2019-08-23 15:15:58 +0000734 kernel_buffer_size = parent_isolate_group_data->kernel_buffer_size();
Alexander Aprelev7d147852018-12-14 23:45:57 +0000735 }
736
737 if (kernel_buffer == NULL && !isolate_run_app_snapshot) {
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000738 dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700739 }
asivaa782dd82020-06-11 01:22:35 +0000740 PathSanitizer script_uri_sanitizer(script_uri);
741 PathSanitizer packages_config_sanitizer(packages_config);
742 flags->null_safety = Dart_DetectNullSafety(
743 script_uri_sanitizer.sanitized_uri(),
744 packages_config_sanitizer.sanitized_uri(),
745 DartUtils::original_working_directory, isolate_snapshot_data,
746 isolate_snapshot_instructions, kernel_buffer, kernel_buffer_size);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700747#endif // !defined(DART_PRECOMPILED_RUNTIME)
748
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000749 auto isolate_group_data = new IsolateGroupData(
750 script_uri, packages_config, app_snapshot, isolate_run_app_snapshot);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000751 if (kernel_buffer != NULL) {
Alexander Aprelev7d147852018-12-14 23:45:57 +0000752 if (parent_kernel_buffer) {
Alexander Aprelev04259972019-07-08 23:49:05 +0000753 isolate_group_data->SetKernelBufferAlreadyOwned(
754 std::move(parent_kernel_buffer), kernel_buffer_size);
Alexander Aprelev7d147852018-12-14 23:45:57 +0000755 } else {
Alexander Aprelev04259972019-07-08 23:49:05 +0000756 isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer,
757 kernel_buffer_size);
Alexander Aprelev7d147852018-12-14 23:45:57 +0000758 }
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000759 }
Siva Chandra71dba8a2018-02-01 15:11:29 +0000760
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700761 Dart_Isolate isolate = NULL;
Ben Konyi63389142018-02-07 19:35:39 +0000762
Martin Kustermannb745cdc2021-07-15 09:35:40 +0000763 IsolateData* isolate_data = nullptr;
Ben Konyi63389142018-02-07 19:35:39 +0000764#if !defined(DART_PRECOMPILED_RUNTIME)
Liam Appelbee427c9c2019-06-26 20:57:46 +0000765 if (!isolate_run_app_snapshot && (isolate_snapshot_data == NULL)) {
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000766 const uint8_t* platform_kernel_buffer = NULL;
767 intptr_t platform_kernel_buffer_size = 0;
asiva0a292642018-08-24 15:45:04 +0000768 dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size);
Ryan Macnaka5c11d72018-05-14 20:58:08 +0000769 if (platform_kernel_buffer == NULL) {
770 platform_kernel_buffer = kernel_buffer;
771 platform_kernel_buffer_size = kernel_buffer_size;
772 }
773 if (platform_kernel_buffer == NULL) {
Ben Konyie35ed9c2018-05-23 20:35:53 +0000774#if defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
775 FATAL(
776 "Binary built with --exclude-kernel-service. Cannot run"
777 " from source.");
778#else
Ben Konyi63389142018-02-07 19:35:39 +0000779 FATAL("platform_program cannot be NULL.");
Ben Konyie35ed9c2018-05-23 20:35:53 +0000780#endif // defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
Ben Konyi63389142018-02-07 19:35:39 +0000781 }
Siva Chandra71dba8a2018-02-01 15:11:29 +0000782 // TODO(sivachandra): When the platform program is unavailable, check if
783 // application kernel binary is self contained or an incremental binary.
784 // Isolate should be created only if it is a self contained kernel binary.
Martin Kustermannb745cdc2021-07-15 09:35:40 +0000785 isolate_data = new IsolateData(isolate_group_data);
Alexander Aprelev04259972019-07-08 23:49:05 +0000786 isolate = Dart_CreateIsolateGroupFromKernel(
Ben Konyiac2c9342019-03-28 16:39:50 +0000787 script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size,
Alexander Aprelev04259972019-07-08 23:49:05 +0000788 flags, isolate_group_data, isolate_data, error);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700789 } else {
Martin Kustermannb745cdc2021-07-15 09:35:40 +0000790 isolate_data = new IsolateData(isolate_group_data);
Ryan Macnak6a65ea92019-10-22 19:02:26 +0000791 isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
792 isolate_snapshot_instructions, flags,
793 isolate_group_data, isolate_data, error);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700794 }
asivaee6351a2018-05-01 22:57:35 +0000795#else
Martin Kustermannb745cdc2021-07-15 09:35:40 +0000796 isolate_data = new IsolateData(isolate_group_data);
Ryan Macnak6a65ea92019-10-22 19:02:26 +0000797 isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
798 isolate_snapshot_instructions, flags,
799 isolate_group_data, isolate_data, error);
Ben Konyi63389142018-02-07 19:35:39 +0000800#endif // !defined(DART_PRECOMPILED_RUNTIME)
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000801
802 Dart_Isolate created_isolate = NULL;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700803 if (isolate == NULL) {
Martin Kustermannb745cdc2021-07-15 09:35:40 +0000804 delete isolate_data;
Alexander Aprelev04259972019-07-08 23:49:05 +0000805 delete isolate_group_data;
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000806 } else {
asivae70a7aa2018-10-10 23:19:24 +0000807 created_isolate = IsolateSetupHelper(
Alexander Aprelev04259972019-07-08 23:49:05 +0000808 isolate, is_main_isolate, script_uri, packages_config,
asivae70a7aa2018-10-10 23:19:24 +0000809 isolate_run_app_snapshot, flags, error, exit_code);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700810 }
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000811 int64_t end = Dart_TimelineGetMicros();
Alexander Aprelev04259972019-07-08 23:49:05 +0000812 Dart_TimelineEvent("CreateIsolateGroupAndSetupHelper", start, end,
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000813 Dart_Timeline_Event_Duration, 0, NULL, NULL);
Alexander Aprelev85ee5ad2018-04-04 23:56:56 +0000814 return created_isolate;
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700815}
816
johnmccutchan@google.comc76b6eb2014-01-14 22:34:43 +0000817#undef CHECK_RESULT
dgrove@google.com4c0f5592011-10-05 05:20:07 +0000818
Alexander Aprelev04259972019-07-08 23:49:05 +0000819static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
820 const char* main,
821 const char* package_root,
822 const char* package_config,
823 Dart_IsolateFlags* flags,
824 void* callback_data,
825 char** error) {
Ivan Posvaf5e3f942015-06-07 17:57:34 +0200826 // The VM should never call the isolate helper with a NULL flags.
827 ASSERT(flags != NULL);
828 ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION);
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000829 ASSERT(package_root == nullptr);
Ivan Posva60eab652015-10-12 09:05:37 -0700830 int exit_code = 0;
asiva1aaebed2018-02-28 01:15:47 +0000831#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700832 if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000833 return CreateAndSetupKernelIsolate(script_uri, package_config, flags, error,
834 &exit_code);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700835 }
asiva1aaebed2018-02-28 01:15:47 +0000836#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
Ben Konyi9bac3272020-08-13 22:04:24 +0000837
838#if !defined(DART_PRECOMPILED_RUNTIME)
839 if (strcmp(script_uri, DART_DEV_ISOLATE_NAME) == 0) {
840 return CreateAndSetupDartDevIsolate(script_uri, package_config, flags,
841 error, &exit_code);
842 }
843#endif // !defined(DART_PRECOMPILED_RUNTIME)
844
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700845 if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000846 return CreateAndSetupServiceIsolate(script_uri, package_config, flags,
847 error, &exit_code);
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700848 }
Ben Konyi9bac3272020-08-13 22:04:24 +0000849
Siva Annamalai4b8cc6b2017-06-02 10:43:32 -0700850 bool is_main_isolate = false;
Alexander Aprelev04259972019-07-08 23:49:05 +0000851 return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main,
Martin Kustermanna94b8ae2020-05-04 14:51:14 +0000852 package_config, flags, callback_data,
853 error, &exit_code);
turnidge@google.com05b5d442012-05-23 18:32:51 +0000854}
855
Alexander Aprelev04259972019-07-08 23:49:05 +0000856static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
Alexander Apreleva53172c2018-10-17 17:12:47 +0000857 Dart_EnterScope();
Alexander Markove64428a2019-01-18 01:41:18 +0000858 Dart_Handle sticky_error = Dart_GetStickyError();
859 if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000860 Syslog::PrintErr("%s\n", Dart_GetError(sticky_error));
Alexander Markove64428a2019-01-18 01:41:18 +0000861 }
Alexander Apreleva53172c2018-10-17 17:12:47 +0000862 Dart_ExitScope();
Vyacheslav Egorova5e1f892017-02-28 21:10:04 +0100863}
864
Alexander Aprelev04259972019-07-08 23:49:05 +0000865static void DeleteIsolateData(void* isolate_group_data, void* callback_data) {
866 auto isolate_data = reinterpret_cast<IsolateData*>(callback_data);
Martin Kustermannb2171f12019-06-26 16:04:27 +0000867 delete isolate_data;
ager@google.comf791a122012-06-29 14:40:17 +0000868}
869
Alexander Aprelev04259972019-07-08 23:49:05 +0000870static void DeleteIsolateGroupData(void* callback_data) {
871 auto isolate_group_data = reinterpret_cast<IsolateGroupData*>(callback_data);
872 delete isolate_group_data;
873}
874
Todd Turnidgee4684c72015-07-14 12:54:07 -0700875static const char* kStdoutStreamId = "Stdout";
876static const char* kStderrStreamId = "Stderr";
877
Todd Turnidgee4684c72015-07-14 12:54:07 -0700878static bool ServiceStreamListenCallback(const char* stream_id) {
879 if (strcmp(stream_id, kStdoutStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -0800880 SetCaptureStdout(true);
Todd Turnidgee4684c72015-07-14 12:54:07 -0700881 return true;
882 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -0800883 SetCaptureStderr(true);
Todd Turnidgee4684c72015-07-14 12:54:07 -0700884 return true;
885 }
886 return false;
887}
888
Todd Turnidgee4684c72015-07-14 12:54:07 -0700889static void ServiceStreamCancelCallback(const char* stream_id) {
890 if (strcmp(stream_id, kStdoutStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -0800891 SetCaptureStdout(false);
Todd Turnidgee4684c72015-07-14 12:54:07 -0700892 } else if (strcmp(stream_id, kStderrStreamId) == 0) {
Todd Turnidgeb243fa52015-11-19 09:24:23 -0800893 SetCaptureStderr(false);
Todd Turnidgee4684c72015-07-14 12:54:07 -0700894 }
Todd Turnidgee4684c72015-07-14 12:54:07 -0700895}
896
Todd Turnidge1166f832016-07-29 11:23:18 -0700897static bool FileModifiedCallback(const char* url, int64_t since) {
Ben Konyi6be8d472018-01-11 14:53:02 -0800898 if (strncmp(url, "file:///", 8) != 0) {
Todd Turnidge1166f832016-07-29 11:23:18 -0700899 // If it isn't a file on local disk, we don't know if it has been
900 // modified.
901 return true;
902 }
903 int64_t data[File::kStatSize];
Zachary Andersond0295c82017-08-30 09:34:34 -0700904 File::Stat(NULL, url + 7, data);
Todd Turnidge1166f832016-07-29 11:23:18 -0700905 if (data[File::kType] == File::kDoesNotExist) {
906 return true;
907 }
908 bool modified = data[File::kModifiedTime] > since;
909 return modified;
910}
911
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -0700912static void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -0700913 info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
914 info->name = "Dart VM";
Carlo Bernaschina491390e2017-08-16 10:59:20 -0700915 Process::GetRSSInformation(&(info->max_rss), &(info->current_rss));
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -0700916}
917
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700918#define CHECK_RESULT(result) \
919 if (Dart_IsError(result)) { \
Zachary Anderson479a97b2016-11-04 12:30:56 -0700920 const int exit_code = Dart_IsCompilationError(result) \
921 ? kCompilationErrorExitCode \
922 : kErrorExitCode; \
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700923 ErrorExit(exit_code, "%s\n", Dart_GetError(result)); \
924 }
925
Sigurd Meldgaardce272da2020-11-17 10:20:00 +0000926void RunMainIsolate(const char* script_name,
927 const char* package_config_override,
928 CommandLineOptions* dart_options) {
Ryan Macnak70e31782021-08-31 19:33:10 +0000929 if (script_name != NULL) {
930 const char* base_name = strrchr(script_name, '/');
931 if (base_name == NULL) {
932 base_name = script_name;
933 } else {
934 base_name++; // Skip '/'.
935 }
936 const intptr_t kMaxNameLength = 64;
937 char name[kMaxNameLength];
938 Utils::SNPrint(name, kMaxNameLength, "dart:%s", base_name);
939 Platform::SetProcessName(name);
940 }
941
Alexander Aprelev04259972019-07-08 23:49:05 +0000942 // Call CreateIsolateGroupAndSetup which creates an isolate and loads up
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700943 // the specified application script.
944 char* error = NULL;
945 int exit_code = 0;
Vyacheslav Egorov7d523172017-08-25 09:48:20 +0200946 Dart_IsolateFlags flags;
947 Dart_IsolateFlagsInitialize(&flags);
Ben Konyi3b1e8332021-07-22 18:15:10 +0000948 flags.is_system_isolate = Options::mark_main_isolate_as_system_isolate();
Vyacheslav Egorov7d523172017-08-25 09:48:20 +0200949
Alexander Aprelev04259972019-07-08 23:49:05 +0000950 Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
Sigurd Meldgaardce272da2020-11-17 10:20:00 +0000951 /* is_main_isolate */ true, script_name, "main",
952 Options::packages_file() == nullptr ? package_config_override
953 : Options::packages_file(),
Ben Konyi9bac3272020-08-13 22:04:24 +0000954 &flags, NULL /* callback_data */, &error, &exit_code);
Martin Kustermanna4af44b2018-06-06 10:56:10 +0000955
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700956 if (isolate == NULL) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000957 Syslog::PrintErr("%s\n", error);
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700958 free(error);
959 error = NULL;
960 Process::TerminateExitCodeHandler();
961 error = Dart_Cleanup();
962 if (error != NULL) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000963 Syslog::PrintErr("VM cleanup failed: %s\n", error);
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700964 free(error);
965 }
Martin Kustermann0ae86972020-03-17 08:49:52 +0000966 dart::embedder::Cleanup();
Zachary Anderson3563dc02015-10-29 23:35:46 -0700967 Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700968 }
Ryan Macnak4d65db8a2016-10-31 15:56:25 -0700969 main_isolate = isolate;
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700970
971 Dart_EnterIsolate(isolate);
972 ASSERT(isolate == Dart_CurrentIsolate());
973 ASSERT(isolate != NULL);
974 Dart_Handle result;
975
976 Dart_EnterScope();
977
Siva Annamalaid46a6962020-06-20 08:02:53 +0000978 auto isolate_group_data =
979 reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
Ryan Macnak2f25dcd2018-09-26 22:49:27 +0000980 if (Options::gen_snapshot_kind() == kKernel) {
Ryan Macnak76842f72017-12-05 17:09:52 +0000981 if (vm_run_app_snapshot) {
Ryan Macnak971f4842019-04-22 20:15:43 +0000982 Syslog::PrintErr(
983 "Cannot create a script snapshot from an app snapshot.\n");
Ryan Macnak76842f72017-12-05 17:09:52 +0000984 // The snapshot would contain references to the app snapshot instead of
985 // the core snapshot.
986 Platform::Exit(kErrorExitCode);
987 }
asiva355c73d2018-09-24 20:38:08 +0000988 Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
Siva Annamalaid46a6962020-06-20 08:02:53 +0000989 isolate_group_data->resolved_packages_config());
Todd Turnidge0d501ad2015-10-06 11:27:26 -0700990 } else {
991 // Lookup the library of the root script.
992 Dart_Handle root_lib = Dart_RootLibrary();
Ryan Macnak37dd8762015-10-29 15:15:46 -0700993
Ryan Macnakcc28d2c2018-10-05 00:36:53 +0000994#if !defined(DART_PRECOMPILED_RUNTIME)
Zachary Andersond7845c62017-09-11 18:58:39 +0000995 if (Options::compile_all()) {
Ryan Macnak9328d722016-01-08 10:19:14 -0800996 result = Dart_CompileAll();
997 CHECK_RESULT(result);
998 }
Siva Annamalaic29b19f2017-11-09 19:05:15 +0000999#endif // !defined(DART_PRECOMPILED_RUNTIME)
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001000
Ryan Macnakcc28d2c2018-10-05 00:36:53 +00001001 if (Dart_IsNull(root_lib)) {
1002 ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
1003 script_name);
1004 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001005
Ryan Macnakcc28d2c2018-10-05 00:36:53 +00001006 // Create a closure for the main entry point which is in the exported
1007 // namespace of the root library or invoke a getter of the same name
1008 // in the exported namespace and return the resulting closure.
1009 Dart_Handle main_closure =
1010 Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
1011 CHECK_RESULT(main_closure);
1012 if (!Dart_IsClosure(main_closure)) {
1013 ErrorExit(kErrorExitCode, "Unable to find 'main' in root library '%s'\n",
1014 script_name);
1015 }
1016
1017 // Call _startIsolate in the isolate library to enable dispatching the
1018 // initial startup message.
1019 const intptr_t kNumIsolateArgs = 2;
1020 Dart_Handle isolate_args[kNumIsolateArgs];
Ben Konyi157ebfe2020-07-21 16:23:18 +00001021 isolate_args[0] = main_closure; // entryPoint
1022 isolate_args[1] = dart_options->CreateRuntimeOptions(); // args
Ryan Macnakcc28d2c2018-10-05 00:36:53 +00001023
1024 Dart_Handle isolate_lib =
1025 Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
1026 result =
1027 Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startMainIsolate"),
1028 kNumIsolateArgs, isolate_args);
1029 CHECK_RESULT(result);
1030
1031 // Keep handling messages until the last active receive port is closed.
1032 result = Dart_RunLoop();
1033 // Generate an app snapshot after execution if specified.
1034 if (Options::gen_snapshot_kind() == kAppJIT) {
1035 if (!Dart_IsCompilationError(result)) {
1036 Snapshot::GenerateAppJIT(Options::snapshot_filename());
Ryan Macnak74f3d1b2017-06-05 16:56:16 -07001037 }
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001038 }
Ryan Macnakcc28d2c2018-10-05 00:36:53 +00001039 CHECK_RESULT(result);
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001040 }
1041
Zachary Andersonf06bf4c2018-02-07 05:08:45 +00001042 WriteDepsFile(isolate);
P.Y. Laligand8f035202017-03-27 06:44:21 -07001043
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001044 Dart_ExitScope();
P.Y. Laligand8f035202017-03-27 06:44:21 -07001045
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001046 // Shutdown the isolate.
1047 Dart_ShutdownIsolate();
Todd Turnidge0d501ad2015-10-06 11:27:26 -07001048}
1049
1050#undef CHECK_RESULT
1051
Zichang Guod6d37ed2020-07-31 21:09:40 +00001052static bool CheckForInvalidPath(const char* path) {
1053 // TODO(zichangguo): "\\?\" is a prefix for paths on Windows.
1054 // Arguments passed are parsed as an URI. "\\?\" causes problems as a part
1055 // of URIs. This is a temporary workaround to prevent VM from crashing.
1056 // Issue: https://github.com/dart-lang/sdk/issues/42779
1057 if (strncmp(path, "\\\\?\\", 4) == 0) {
1058 Syslog::PrintErr("\\\\?\\ prefix is not supported");
1059 return false;
1060 }
1061 return true;
1062}
1063
asiva8e4421a2019-12-27 19:46:15 +00001064// Observatory assets are not included in a product build.
1065#if !defined(PRODUCT)
John McCutchan2844eb82015-10-26 07:21:23 -07001066extern unsigned int observatory_assets_archive_len;
John McCutchan33814bd2015-10-27 08:56:02 -07001067extern const uint8_t* observatory_assets_archive;
John McCutchan2844eb82015-10-26 07:21:23 -07001068
1069Dart_Handle GetVMServiceAssetsArchiveCallback() {
John McCutchancc0f2972015-12-16 12:35:58 -08001070 uint8_t* decompressed = NULL;
Ryan Macnak7dfe62f2017-08-11 12:18:16 -07001071 intptr_t decompressed_len = 0;
Zachary Anderson479a97b2016-11-04 12:30:56 -07001072 Decompress(observatory_assets_archive, observatory_assets_archive_len,
1073 &decompressed, &decompressed_len);
1074 Dart_Handle tar_file =
1075 DartUtils::MakeUint8Array(decompressed, decompressed_len);
John McCutchancc0f2972015-12-16 12:35:58 -08001076 // Free decompressed memory as it has been copied into a Dart array.
1077 free(decompressed);
1078 return tar_file;
John McCutchan2844eb82015-10-26 07:21:23 -07001079}
asiva8e4421a2019-12-27 19:46:15 +00001080#else // !defined(PRODUCT)
Ivan Posva9535aa62016-03-04 16:05:54 -08001081static Dart_GetVMServiceAssetsArchive GetVMServiceAssetsArchiveCallback = NULL;
asiva8e4421a2019-12-27 19:46:15 +00001082#endif // !defined(PRODUCT)
John McCutchan2844eb82015-10-26 07:21:23 -07001083
johnmccutchan@google.coma80d3282013-11-26 18:13:51 +00001084void main(int argc, char** argv) {
Ben Konyi157ebfe2020-07-21 16:23:18 +00001085 char* script_name = nullptr;
Sigurd Meldgaardce272da2020-11-17 10:20:00 +00001086 // Allows the dartdev process to point to the desired package_config.
1087 char* package_config_override = nullptr;
Zach Anderson664f7562018-06-13 20:50:34 +00001088 const int EXTRA_VM_ARGUMENTS = 10;
Srdjan Mitrovicfc3cd692015-05-27 17:11:35 -07001089 CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
Ben Konyi444490d2020-05-13 19:58:56 +00001090 CommandLineOptions dart_options(argc + EXTRA_VM_ARGUMENTS);
asiva@google.comc7f58ad2012-06-13 17:48:47 +00001091 bool print_flags_seen = false;
tball@google.comb3cae062013-04-05 20:55:10 +00001092 bool verbose_debug_seen = false;
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001093
Ben Konyi103d54b2019-09-24 20:43:20 +00001094 // Perform platform specific initialization.
1095 if (!Platform::Initialize()) {
1096 Syslog::PrintErr("Initialization failed\n");
Ryan Macnak1ed184b2017-10-23 22:19:39 +00001097 Platform::Exit(kErrorExitCode);
sgjesse@google.comd7c8c1f2011-11-23 14:49:18 +00001098 }
1099
Ben Konyi3c8d3b62018-03-12 20:31:09 +00001100 // Save the console state so we can restore it at shutdown.
1101 Console::SaveConfig();
1102
ager@google.com28b43142012-11-13 15:03:23 +00001103 // On Windows, the argv strings are code page encoded and not
1104 // utf8. We need to convert them to utf8.
Soren Gjesse0415d922015-06-24 10:36:05 +02001105 bool argv_converted = ShellUtils::GetUtf8Argv(argc, argv);
ager@google.com28b43142012-11-13 15:03:23 +00001106
Zachary Andersond7845c62017-09-11 18:58:39 +00001107#if !defined(DART_PRECOMPILED_RUNTIME)
1108 // Processing of some command line flags directly manipulates dfe.
1109 Options::set_dfe(&dfe);
1110#endif // !defined(DART_PRECOMPILED_RUNTIME)
1111
Zach Anderson664f7562018-06-13 20:50:34 +00001112 // When running from the command line we assume that we are optimizing for
1113 // throughput, and therefore use a larger new gen semi space size and a faster
1114 // new gen growth factor unless others have been specified.
1115 if (kWordSize <= 4) {
1116 vm_options.AddArgument("--new_gen_semi_max_size=16");
1117 } else {
1118 vm_options.AddArgument("--new_gen_semi_max_size=32");
1119 }
1120 vm_options.AddArgument("--new_gen_growth_factor=4");
1121
Samir Jindelafac6a32019-10-03 13:40:12 +00001122 AppSnapshot* app_snapshot = nullptr;
1123#if defined(DART_PRECOMPILED_RUNTIME)
Clement Skau46b58392019-09-11 10:56:57 +00001124 // If the executable binary contains the runtime together with an appended
1125 // snapshot, load and run that.
1126 // Any arguments passed to such an executable are meant for the actual
1127 // application so skip all Dart VM flag parsing.
Clement Skau46b58392019-09-11 10:56:57 +00001128
Clement Skau8d8faa7d2019-10-18 10:30:48 +00001129 const size_t kPathBufSize = PATH_MAX + 1;
1130 char executable_path[kPathBufSize];
1131 if (Platform::ResolveExecutablePathInto(executable_path, kPathBufSize) > 0) {
1132 app_snapshot = Snapshot::TryReadAppendedAppSnapshotElf(executable_path);
1133 if (app_snapshot != nullptr) {
1134 script_name = argv[0];
Clement Skau46b58392019-09-11 10:56:57 +00001135
Clement Skau8d8faa7d2019-10-18 10:30:48 +00001136 // Store the executable name.
1137 Platform::SetExecutableName(argv[0]);
1138
1139 // Parse out options to be passed to dart main.
1140 for (int i = 1; i < argc; i++) {
1141 dart_options.AddArgument(argv[i]);
1142 }
Clement Skau46b58392019-09-11 10:56:57 +00001143 }
Samir Jindelafac6a32019-10-03 13:40:12 +00001144 }
1145#endif
1146
1147 // Parse command line arguments.
Ben Konyi65486942020-02-06 00:04:09 +00001148 if (app_snapshot == nullptr) {
Sigurd Meldgaardf3fe9dc2020-12-04 14:22:10 +00001149 bool success = Options::ParseArguments(
Ben Konyi65486942020-02-06 00:04:09 +00001150 argc, argv, vm_run_app_snapshot, &vm_options, &script_name,
1151 &dart_options, &print_flags_seen, &verbose_debug_seen);
Sigurd Meldgaardf3fe9dc2020-12-04 14:22:10 +00001152 if (!success) {
Ben Konyi65486942020-02-06 00:04:09 +00001153 if (Options::help_option()) {
1154 Options::PrintUsage();
1155 Platform::Exit(0);
1156 } else if (Options::version_option()) {
1157 Options::PrintVersion();
1158 Platform::Exit(0);
1159 } else if (print_flags_seen) {
1160 // Will set the VM flags, print them out and then we exit as no
1161 // script was specified on the command line.
1162 char* error =
1163 Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
1164 if (error != NULL) {
1165 Syslog::PrintErr("Setting VM flags failed: %s\n", error);
1166 free(error);
1167 Platform::Exit(kErrorExitCode);
1168 }
1169 Platform::Exit(0);
1170 } else {
Ben Konyid2855e72021-08-13 23:01:51 +00001171 // This usage error case will only be invoked when
1172 // Options::disable_dart_dev() is false.
Ben Konyi65486942020-02-06 00:04:09 +00001173 Options::PrintUsage();
Ryan Macnak607f4f52018-05-01 20:54:38 +00001174 Platform::Exit(kErrorExitCode);
1175 }
Ben Konyi65486942020-02-06 00:04:09 +00001176 }
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001177 }
Ben Konyi65486942020-02-06 00:04:09 +00001178
Zach Anderson27c79f92018-09-06 02:23:21 +00001179 DartUtils::SetEnvironment(Options::environment());
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001180
Vyacheslav Egorov040ef6a2018-11-30 11:15:06 +00001181 if (Options::suppress_core_dump()) {
1182 Platform::SetCoreDumpResourceLimit(0);
1183 } else {
1184 InitializeCrashpadClient();
1185 }
Vyacheslav Egorov2c83eb52018-10-24 13:30:16 +00001186
Florian Schneider63e3f4d2016-07-13 09:41:06 -07001187 Loader::InitOnce();
1188
Ben Konyi157ebfe2020-07-21 16:23:18 +00001189 auto try_load_snapshots_lambda = [&](void) -> void {
1190 if (app_snapshot == nullptr) {
1191 // For testing purposes we add a flag to debug-mode to use the
1192 // in-memory ELF loader.
1193 const bool force_load_elf_from_memory =
1194 false DEBUG_ONLY(|| Options::force_load_elf_from_memory());
1195 app_snapshot =
1196 Snapshot::TryReadAppSnapshot(script_name, force_load_elf_from_memory);
1197 }
1198 if (app_snapshot != nullptr) {
1199 vm_run_app_snapshot = true;
1200 app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
1201 &app_isolate_snapshot_data,
1202 &app_isolate_snapshot_instructions);
1203 }
1204 };
1205
1206 // At this point, script_name now points to a script if DartDev is disabled
1207 // or a valid file path was provided as the first non-flag argument.
1208 // Otherwise, script_name can be NULL if DartDev should be run.
1209 if (script_name != nullptr) {
Zichang Guod6d37ed2020-07-31 21:09:40 +00001210 if (!CheckForInvalidPath(script_name)) {
1211 Platform::Exit(0);
1212 }
Ben Konyi157ebfe2020-07-21 16:23:18 +00001213 try_load_snapshots_lambda();
Ryan Macnak3d00ecd2016-10-14 09:57:54 -07001214 }
1215
Zachary Andersond7845c62017-09-11 18:58:39 +00001216 if (Options::gen_snapshot_kind() == kAppJIT) {
Ryan Macnakad32e932016-10-07 10:34:57 -07001217 vm_options.AddArgument("--fields_may_be_reset");
1218 }
Ryan Macnak7546ef12016-05-06 12:40:04 -07001219#if defined(DART_PRECOMPILED_RUNTIME)
Florian Schneider23dd0b92016-02-04 16:33:37 -08001220 vm_options.AddArgument("--precompilation");
Florian Schneider0f486902016-02-02 17:51:15 -08001221#endif
Zach Anderson00e31092018-07-31 17:09:31 +00001222 // If we need to write an app-jit snapshot or a depfile, then add an exit
1223 // hook that writes the snapshot and/or depfile as appropriate.
1224 if ((Options::gen_snapshot_kind() == kAppJIT) ||
1225 (Options::depfile() != NULL)) {
1226 Process::SetExitHook(OnExitHook);
Ryan Macnak4d65db8a2016-10-31 15:56:25 -07001227 }
Florian Schneider0f486902016-02-02 17:51:15 -08001228
Ben Konyi103d54b2019-09-24 20:43:20 +00001229 char* error = nullptr;
1230 if (!dart::embedder::InitOnce(&error)) {
1231 Syslog::PrintErr("Standalone embedder initialization failed: %s\n", error);
1232 free(error);
1233 Platform::Exit(kErrorExitCode);
1234 }
1235
Vyacheslav Egorovc9107382018-07-17 09:04:05 +00001236 error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
Ryan Macnak607f4f52018-05-01 20:54:38 +00001237 if (error != NULL) {
Ryan Macnak971f4842019-04-22 20:15:43 +00001238 Syslog::PrintErr("Setting VM flags failed: %s\n", error);
Ryan Macnak607f4f52018-05-01 20:54:38 +00001239 free(error);
1240 Platform::Exit(kErrorExitCode);
1241 }
Vyacheslav Egorov0fe889d2017-10-23 11:27:47 +00001242
1243// Note: must read platform only *after* VM flags are parsed because
1244// they might affect how the platform is loaded.
Siva Chandra8b405072017-06-22 10:10:42 -07001245#if !defined(DART_PRECOMPILED_RUNTIME)
Ben Konyi19875e92020-09-10 17:53:19 +00001246 // Load vm_platform_strong.dill for dart:* source support.
1247 dfe.Init();
asivaac520f92021-01-26 03:01:58 +00001248 dfe.set_verbosity(Options::verbosity_level());
Ben Konyi157ebfe2020-07-21 16:23:18 +00001249 if (script_name != nullptr) {
Ben Konyi157ebfe2020-07-21 16:23:18 +00001250 uint8_t* application_kernel_buffer = NULL;
1251 intptr_t application_kernel_buffer_size = 0;
1252 dfe.ReadScript(script_name, &application_kernel_buffer,
1253 &application_kernel_buffer_size);
1254 if (application_kernel_buffer != NULL) {
1255 // Since we loaded the script anyway, save it.
1256 dfe.set_application_kernel_buffer(application_kernel_buffer,
1257 application_kernel_buffer_size);
1258 Options::dfe()->set_use_dfe();
1259 }
Siva Chandra8b405072017-06-22 10:10:42 -07001260 }
1261#endif
1262
johnmccutchan@google.com9b1f39b2015-02-12 21:22:34 +00001263 // Initialize the Dart VM.
Adam Barthfac99f32016-08-09 12:25:29 -07001264 Dart_InitializeParams init_params;
1265 memset(&init_params, 0, sizeof(init_params));
1266 init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
Ryan Macnakb46af1e2017-01-23 10:25:02 -08001267 init_params.vm_snapshot_data = vm_snapshot_data;
1268 init_params.vm_snapshot_instructions = vm_snapshot_instructions;
Alexander Aprelev04259972019-07-08 23:49:05 +00001269 init_params.create_group = CreateIsolateGroupAndSetup;
1270 init_params.initialize_isolate = OnIsolateInitialize;
1271 init_params.shutdown_isolate = OnIsolateShutdown;
1272 init_params.cleanup_isolate = DeleteIsolateData;
1273 init_params.cleanup_group = DeleteIsolateGroupData;
Adam Barthfac99f32016-08-09 12:25:29 -07001274 init_params.file_open = DartUtils::OpenFile;
1275 init_params.file_read = DartUtils::ReadFile;
1276 init_params.file_write = DartUtils::WriteFile;
1277 init_params.file_close = DartUtils::CloseFile;
1278 init_params.entropy_source = DartUtils::EntropySource;
1279 init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
Siva Annamalai73d30072017-08-11 12:38:22 -07001280#if !defined(DART_PRECOMPILED_RUNTIME)
asiva355c73d2018-09-24 20:38:08 +00001281 init_params.start_kernel_isolate =
1282 dfe.UseDartFrontend() && dfe.CanUseDartFrontend();
Siva Annamalai73d30072017-08-11 12:38:22 -07001283#else
1284 init_params.start_kernel_isolate = false;
1285#endif
Adam Barthfac99f32016-08-09 12:25:29 -07001286
Ryan Macnak607f4f52018-05-01 20:54:38 +00001287 error = Dart_Initialize(&init_params);
Zachary Anderson7093f292015-09-15 12:49:52 -07001288 if (error != NULL) {
Martin Kustermann0ae86972020-03-17 08:49:52 +00001289 dart::embedder::Cleanup();
Ryan Macnak971f4842019-04-22 20:15:43 +00001290 Syslog::PrintErr("VM initialization failed: %s\n", error);
Zachary Anderson7093f292015-09-15 12:49:52 -07001291 free(error);
Zachary Anderson3563dc02015-10-29 23:35:46 -07001292 Platform::Exit(kErrorExitCode);
johnmccutchan@google.com9b1f39b2015-02-12 21:22:34 +00001293 }
1294
Todd Turnidgee4684c72015-07-14 12:54:07 -07001295 Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
1296 &ServiceStreamCancelCallback);
Todd Turnidge1166f832016-07-29 11:23:18 -07001297 Dart_SetFileModifiedCallback(&FileModifiedCallback);
Carlo Bernaschina0cbbeeb2017-08-14 17:02:22 -07001298 Dart_SetEmbedderInformationCallback(&EmbedderInformationCallback);
Ben Konyi157ebfe2020-07-21 16:23:18 +00001299 bool ran_dart_dev = false;
1300 bool should_run_user_program = true;
1301#if !defined(DART_PRECOMPILED_RUNTIME)
1302 if (DartDevIsolate::should_run_dart_dev() && !Options::disable_dart_dev() &&
1303 Options::gen_snapshot_kind() == SnapshotKind::kNone) {
1304 DartDevIsolate::DartDev_Result dartdev_result = DartDevIsolate::RunDartDev(
Sigurd Meldgaardce272da2020-11-17 10:20:00 +00001305 CreateIsolateGroupAndSetup, &package_config_override, &script_name,
Ben Konyi157ebfe2020-07-21 16:23:18 +00001306 &dart_options);
1307 ASSERT(dartdev_result != DartDevIsolate::DartDev_Result_Unknown);
1308 ran_dart_dev = true;
1309 should_run_user_program =
1310 (dartdev_result == DartDevIsolate::DartDev_Result_Run);
1311 if (should_run_user_program) {
1312 try_load_snapshots_lambda();
1313 }
1314 }
1315#endif // !defined(DART_PRECOMPILED_RUNTIME)
johnmccutchan@google.com42f5a392013-07-16 22:17:52 +00001316
Ben Konyi157ebfe2020-07-21 16:23:18 +00001317 if (should_run_user_program) {
Ben Konyi49d7eba2020-07-27 21:51:03 +00001318 if (!Dart_IsPrecompiledRuntime() && Snapshot::IsAOTSnapshot(script_name)) {
1319 Syslog::PrintErr(
1320 "%s is an AOT snapshot and should be run with 'dartaotruntime'\n",
1321 script_name);
1322 Platform::Exit(kErrorExitCode);
1323 } else {
1324 // Run the main isolate until we aren't told to restart.
Sigurd Meldgaardce272da2020-11-17 10:20:00 +00001325 RunMainIsolate(script_name, package_config_override, &dart_options);
Ben Konyi157ebfe2020-07-21 16:23:18 +00001326 }
hausner@google.com91593892011-12-07 22:13:49 +00001327 }
hausner@google.com95be4612012-05-04 15:25:49 +00001328
ager@google.comed3338d2012-02-01 18:16:45 +00001329 // Terminate process exit-code handler.
1330 Process::TerminateExitCodeHandler();
ajohnsen@google.com1e2289e2013-07-17 07:26:05 +00001331
Zachary Anderson7093f292015-09-15 12:49:52 -07001332 error = Dart_Cleanup();
1333 if (error != NULL) {
Ryan Macnak971f4842019-04-22 20:15:43 +00001334 Syslog::PrintErr("VM cleanup failed: %s\n", error);
Zachary Anderson7093f292015-09-15 12:49:52 -07001335 free(error);
1336 }
Martin Kustermann0ae86972020-03-17 08:49:52 +00001337 const intptr_t global_exit_code = Process::GlobalExitCode();
1338 dart::embedder::Cleanup();
Zachary Anderson9395a5b2015-09-01 17:53:03 -07001339
Ryan Macnaka317b902017-02-16 13:54:57 -08001340 delete app_snapshot;
Ryan Macnak26a364f2017-01-17 15:59:41 -08001341 free(app_script_uri);
Ben Konyi157ebfe2020-07-21 16:23:18 +00001342 if (ran_dart_dev && script_name != nullptr) {
1343 free(script_name);
1344 }
Ryan Macnak26a364f2017-01-17 15:59:41 -08001345
ager@google.com28b43142012-11-13 15:03:23 +00001346 // Free copied argument strings if converted.
1347 if (argv_converted) {
Zachary Andersonc75a8172016-03-14 11:08:52 -07001348 for (int i = 0; i < argc; i++) {
1349 free(argv[i]);
1350 }
ager@google.com28b43142012-11-13 15:03:23 +00001351 }
ager@google.com7031be22012-02-01 14:19:25 +00001352
sgjesse@google.com36a67fa2013-10-31 05:46:57 +00001353 // Free environment if any.
Zachary Andersond7845c62017-09-11 18:58:39 +00001354 Options::DestroyEnvironment();
sgjesse@google.com36a67fa2013-10-31 05:46:57 +00001355
Martin Kustermann0ae86972020-03-17 08:49:52 +00001356 Platform::Exit(global_exit_code);
dgrove@google.com4c0f5592011-10-05 05:20:07 +00001357}
smok@google.comebbc2022013-04-25 14:22:30 +00001358
1359} // namespace bin
1360} // namespace dart
1361
1362int main(int argc, char** argv) {
johnmccutchan@google.coma80d3282013-11-26 18:13:51 +00001363 dart::bin::main(argc, argv);
1364 UNREACHABLE();
smok@google.comebbc2022013-04-25 14:22:30 +00001365}