Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dartdev_isolate.cc
Go to the documentation of this file.
1// Copyright (c) 2020, 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
6
7#if !defined(DART_PRECOMPILED_RUNTIME)
8
9#include <functional>
10#include <memory>
11
12#include "bin/directory.h"
13#include "bin/error_exit.h"
14#include "bin/exe_utils.h"
15#include "bin/file.h"
16#include "bin/lockers.h"
17#include "bin/platform.h"
18#include "bin/process.h"
20#include "platform/utils.h"
21
22#define CHECK_RESULT(result) \
23 if (Dart_IsError(result)) { \
24 ProcessError(Dart_GetError(result), kErrorExitCode); \
25 if (send_port_id != ILLEGAL_PORT) { \
26 Dart_CloseNativePort(send_port_id); \
27 } \
28 Dart_ExitScope(); \
29 Dart_ShutdownIsolate(); \
30 return; \
31 }
32
33namespace dart {
34namespace bin {
35
36DartDevIsolate::DartDevRunner DartDevIsolate::runner_ =
37 DartDevIsolate::DartDevRunner();
38bool DartDevIsolate::should_run_dart_dev_ = false;
39bool DartDevIsolate::print_usage_error_ = false;
40Monitor* DartDevIsolate::DartDevRunner::monitor_ = new Monitor();
41DartDevIsolate::DartDev_Result DartDevIsolate::DartDevRunner::result_ =
43char** DartDevIsolate::DartDevRunner::script_ = nullptr;
44char** DartDevIsolate::DartDevRunner::package_config_override_ = nullptr;
45std::unique_ptr<char*[], void (*)(char*[])>
46 DartDevIsolate::DartDevRunner::argv_ =
47 std::unique_ptr<char*[], void (*)(char**)>(nullptr, [](char**) {});
48intptr_t DartDevIsolate::DartDevRunner::argc_ = 0;
49
50bool DartDevIsolate::ShouldParseCommand(const char* script_uri) {
51 // If script_uri is a known DartDev command, we should not try to run it.
52 //
53 // Otherwise if script_uri is not a file path or of a known URI scheme, we
54 // assume this is a mistyped DartDev command.
55 //
56 // This should be kept in sync with the commands in
57 // `pkg/dartdev/lib/dartdev.dart`.
58 return (
59 (strcmp(script_uri, "analyze") == 0) ||
60 (strcmp(script_uri, "compilation-server") == 0) ||
61 (strcmp(script_uri, "build") == 0) ||
62 (strcmp(script_uri, "compile") == 0) ||
63 (strcmp(script_uri, "create") == 0) ||
64 (strcmp(script_uri, "development-service") == 0) ||
65 (strcmp(script_uri, "devtools") == 0) ||
66 (strcmp(script_uri, "doc") == 0) || (strcmp(script_uri, "fix") == 0) ||
67 (strcmp(script_uri, "format") == 0) ||
68 (strcmp(script_uri, "info") == 0) || (strcmp(script_uri, "pub") == 0) ||
69 (strcmp(script_uri, "run") == 0) || (strcmp(script_uri, "test") == 0) ||
70 (strcmp(script_uri, "info") == 0) ||
71 (strcmp(script_uri, "language-server") == 0) ||
72 (strcmp(script_uri, "tooling-daemon") == 0) ||
73 (!File::ExistsUri(nullptr, script_uri) &&
74 (strncmp(script_uri, "http://", 7) != 0) &&
75 (strncmp(script_uri, "https://", 8) != 0) &&
76 (strncmp(script_uri, "file://", 7) != 0) &&
77 (strncmp(script_uri, "package:", 8) != 0) &&
78 (strncmp(script_uri, "google3://", 10) != 0)));
79}
80
81Utils::CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(
82 const char* filename) {
83 // |dir_prefix| includes the last path separator.
85
86 // First assume we're in dart-sdk/bin.
87 char* snapshot_path =
88 Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
89 if (File::Exists(nullptr, snapshot_path)) {
90 return Utils::CreateCStringUniquePtr(snapshot_path);
91 }
92 free(snapshot_path);
93
94 // If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
95 // directories. Try to use a snapshot from a previously built SDK.
96 snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
97 if (File::Exists(nullptr, snapshot_path)) {
98 return Utils::CreateCStringUniquePtr(snapshot_path);
99 }
100 free(snapshot_path);
101 return Utils::CreateCStringUniquePtr(nullptr);
102}
103
105 return TryResolveArtifactPath("dartdev.dart.snapshot");
106}
107
109 Dart_IsolateGroupCreateCallback create_isolate,
110 char** packages_file,
111 char** script,
112 CommandLineOptions* dart_options) {
113 create_isolate_ = create_isolate;
114 dart_options_ = dart_options;
115 package_config_override_ = packages_file;
116 script_ = script;
117
118 // We've encountered an error during preliminary argument parsing so we'll
119 // output the standard help message and exit with an error code.
120 if (print_usage_error_) {
121 dart_options_->Reset();
122 dart_options_->AddArgument("--help");
123 }
124
125 MonitorLocker locker(monitor_);
126 int result = Thread::Start("DartDev Runner", RunCallback,
127 reinterpret_cast<uword>(this));
128 if (result != 0) {
129 FATAL("Failed to start DartDev thread: %d", result);
130 }
132
133 if (result_ == DartDevIsolate::DartDev_Result_Run) {
134 // Clear the DartDev dart_options and replace them with the processed
135 // options provided by DartDev.
136 dart_options_->Reset();
137 dart_options_->AddArguments(const_cast<const char**>(argv_.get()), argc_);
138 }
139}
140
142 return message->value.as_array.values[index];
143}
144
145void DartDevIsolate::DartDevRunner::DartDevResultCallback(
146 Dart_Port dest_port_id,
148 // These messages are produced in pkg/dartdev/lib/src/vm_interop_handler.dart.
150 int32_t type = GetArrayItem(message, 0)->value.as_int32;
151 switch (type) {
155 auto item2 = GetArrayItem(message, 2);
156
157 ASSERT(item2->type == Dart_CObject_kString ||
158 item2->type == Dart_CObject_kNull);
159
160 auto item3 = GetArrayItem(message, 3);
161
162 ASSERT(item3->type == Dart_CObject_kBool);
163
164 if (*script_ != nullptr) {
165 free(*script_);
166 }
167 if (*package_config_override_ != nullptr) {
168 free(*package_config_override_);
169 *package_config_override_ = nullptr;
170 }
171 *script_ = Utils::StrDup(GetArrayItem(message, 1)->value.as_string);
172
173 if (item2->type == Dart_CObject_kString) {
174 *package_config_override_ = Utils::StrDup(item2->value.as_string);
175 }
176
179 argc_ = args->value.as_array.length;
180 Dart_CObject** dart_args = args->value.as_array.values;
181
182 auto deleter = [](char** args) {
183 for (intptr_t i = 0; i < argc_; ++i) {
184 free(args[i]);
185 }
186 delete[] args;
187 };
188 argv_ =
189 std::unique_ptr<char*[], void (*)(char**)>(new char*[argc_], deleter);
190 for (intptr_t i = 0; i < argc_; ++i) {
191 argv_[i] = Utils::StrDup(dart_args[i]->value.as_string);
192 }
193 break;
194 }
197 int32_t dartdev_exit_code = GetArrayItem(message, 1)->value.as_int32;
198
199 // If we're given a non-zero exit code, DartDev is signaling for us to
200 // shutdown.
201 int32_t exit_code =
202 print_usage_error_ ? kErrorExitCode : dartdev_exit_code;
204
205 // If DartDev hasn't signaled for us to do anything else, we can assume
206 // there's nothing else for the VM to run and that we can exit.
209 }
210
211 // DartDev is done processing the command. Unblock the main thread and
212 // continue the launch procedure.
213 DartDevRunner::monitor_->Notify();
214 break;
215 }
216 default:
217 UNREACHABLE();
218 }
219}
220
221void DartDevIsolate::DartDevRunner::RunCallback(uword args) {
222 MonitorLocker locker_(DartDevRunner::monitor_);
223 DartDevRunner* runner = reinterpret_cast<DartDevRunner*>(args);
224
225 // Hardcode flags to match those used to generate the DartDev snapshot.
228 flags.enable_asserts = false;
229 flags.use_field_guards = true;
230 flags.use_osr = true;
231 flags.is_system_isolate = true;
232 flags.branch_coverage = false;
233
234 char* error = nullptr;
235 Dart_Isolate dartdev_isolate = runner->create_isolate_(
237 runner->packages_file_, &flags, /* callback_data */ nullptr,
238 const_cast<char**>(&error));
239
240 if (dartdev_isolate == nullptr) {
241 ProcessError(error, kErrorExitCode);
242 free(error);
243 return;
244 }
245
246 Dart_EnterIsolate(dartdev_isolate);
248
249 // Retrieve the DartDev entrypoint.
250 Dart_Port send_port_id = ILLEGAL_PORT;
251 Dart_Handle root_lib = Dart_RootLibrary();
252 Dart_Handle main_closure =
253 Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
254 CHECK_RESULT(main_closure);
255
256 if (!Dart_IsClosure(main_closure)) {
257 ProcessError("Unable to find 'main' in root library 'dartdev'",
261 return;
262 }
263
264 // Create a SendPort that DartDev can use to communicate its results over.
265 send_port_id =
266 Dart_NewNativePort(DART_DEV_ISOLATE_NAME, DartDevResultCallback, false);
267 ASSERT(send_port_id != ILLEGAL_PORT);
268 Dart_Handle send_port = Dart_NewSendPort(send_port_id);
269 CHECK_RESULT(send_port);
270
271 const intptr_t kNumIsolateArgs = 4;
272 Dart_Handle isolate_args[kNumIsolateArgs];
273 isolate_args[0] = main_closure; // entryPoint
274 isolate_args[1] = runner->dart_options_->CreateRuntimeOptions(); // args
275 isolate_args[2] = send_port; // message
276 isolate_args[3] = Dart_True(); // isSpawnUri
277
278 Dart_Handle isolate_lib =
281 Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startIsolate"),
282 kNumIsolateArgs, isolate_args);
285
286 Dart_CloseNativePort(send_port_id);
287
290}
291
292void DartDevIsolate::DartDevRunner::ProcessError(const char* msg,
293 int32_t exit_code) {
294 Syslog::PrintErr("%s.\n", msg);
297 DartDevRunner::monitor_->Notify();
298}
299
301 Dart_IsolateGroupCreateCallback create_isolate,
302 char** packages_file,
303 char** script,
304 CommandLineOptions* dart_options) {
305 runner_.Run(create_isolate, packages_file, script, dart_options);
306 return runner_.result();
307}
308
309} // namespace bin
310} // namespace dart
311
312#endif // if !defined(DART_PRECOMPILED_RUNTIME)
#define UNREACHABLE()
Definition assert.h:248
static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static char * StrDup(const char *s)
static CStringUniquePtr CreateCStringUniquePtr(char *str)
Definition utils.cc:257
std::unique_ptr< char, decltype(std::free) * > CStringUniquePtr
Definition utils.h:644
static char * SCreate(const char *format,...) PRINTF_ATTRIBUTE(1
Definition utils.cc:231
void AddArguments(const char **argv, int argc)
Definition dartutils.h:77
void AddArgument(const char *argument)
Definition dartutils.h:68
void Run(Dart_IsolateGroupCreateCallback create_isolate, char **package_config_override_, char **script, CommandLineOptions *dart_options)
static Utils::CStringUniquePtr TryResolveDartDevSnapshotPath()
static DartDev_Result RunDartDev(Dart_IsolateGroupCreateCallback create_isolate, char **packages_file, char **script, CommandLineOptions *dart_options)
static bool ShouldParseCommand(const char *script_uri)
static Utils::CStringUniquePtr GetDirectoryPrefixFromExeName()
Definition exe_utils.cc:68
static bool Exists(Namespace *namespc, const char *path)
static bool ExistsUri(Namespace *namespc, const char *uri)
static constexpr int64_t kNoTimeout
Definition thread.h:79
WaitResult WaitMicros(int64_t micros)
static void SetGlobalExitCode(int exit_code)
Definition process.h:129
static int Start(const char *name, ThreadStartFunction function, uword parameters)
Dart_Isolate(* Dart_IsolateGroupCreateCallback)(const char *script_uri, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *isolate_data, char **error)
Definition dart_api.h:653
#define ILLEGAL_PORT
Definition dart_api.h:1530
int64_t Dart_Port
Definition dart_api.h:1524
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition dart_api.h:88
@ Dart_CObject_kString
@ Dart_CObject_kArray
@ Dart_CObject_kNull
@ Dart_CObject_kInt32
@ Dart_CObject_kBool
#define CHECK_RESULT(result)
#define DART_DEV_ISOLATE_NAME
#define ASSERT(E)
#define FATAL(error)
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
Win32Message message
static Dart_CObject * GetArrayItem(Dart_CObject *message, intptr_t index)
constexpr int kErrorExitCode
Definition error_exit.h:18
Dart_ShutdownIsolate()
DART_EXPORT void Dart_EnterScope()
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_True()
DART_EXPORT Dart_Handle Dart_RootLibrary()
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags *flags)
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
uintptr_t uword
Definition globals.h:501
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id)
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id)
DART_EXPORT Dart_Handle Dart_RunLoop()
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT Dart_Port Dart_NewNativePort(const char *name, Dart_NativeMessageHandler handler, bool handle_concurrently)
DART_EXPORT bool Dart_IsClosure(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
union _Dart_CObject::@86 value
struct _Dart_CObject::@86::@89 as_array
struct _Dart_CObject ** values