1 | // Copyright (c) 2016, 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 "vm/kernel_isolate.h" |
6 | |
7 | #include "include/dart_native_api.h" |
8 | #include "vm/compiler/jit/compiler.h" |
9 | #include "vm/dart_api_impl.h" |
10 | #include "vm/dart_entry.h" |
11 | #include "vm/flags.h" |
12 | #include "vm/isolate.h" |
13 | #include "vm/lockers.h" |
14 | #include "vm/message.h" |
15 | #include "vm/message_handler.h" |
16 | #include "vm/native_arguments.h" |
17 | #include "vm/native_entry.h" |
18 | #include "vm/native_message_handler.h" |
19 | #include "vm/object.h" |
20 | #include "vm/object_store.h" |
21 | #include "vm/port.h" |
22 | #include "vm/service.h" |
23 | #include "vm/symbols.h" |
24 | #include "vm/thread_pool.h" |
25 | #include "vm/timeline.h" |
26 | |
27 | #if !defined(DART_PRECOMPILED_RUNTIME) |
28 | |
29 | namespace dart { |
30 | |
31 | #define Z (T->zone()) |
32 | |
33 | DEFINE_FLAG(bool, trace_kernel, false, "Trace Kernel service requests." ); |
34 | DEFINE_FLAG(bool, |
35 | suppress_fe_warnings, |
36 | false, |
37 | "Suppress warnings from the FE." ); |
38 | DEFINE_FLAG(charp, |
39 | kernel_multiroot_filepaths, |
40 | NULL, |
41 | "Comma-separated list of file paths that should be treated as roots" |
42 | " by frontend compiler." ); |
43 | DEFINE_FLAG(charp, |
44 | kernel_multiroot_scheme, |
45 | NULL, |
46 | "URI scheme that replaces filepaths prefixes specified" |
47 | " by kernel_multiroot_filepaths option" ); |
48 | |
49 | // Tags used to indicate different requests to the dart frontend. |
50 | // |
51 | // Current tags include the following: |
52 | // 0 - Perform normal compilation. |
53 | // 1 - Update in-memory file system with in-memory sources (used by tests). |
54 | // 2 - Accept last compilation result. |
55 | // 3 - APP JIT snapshot training run for kernel_service. |
56 | // 4 - Compile expressions in context (used by expression evaluation). |
57 | // 5 - Generate dependencies used to create a dependencies file. |
58 | // 6 - Triggers shutdown of the kernel isolate. |
59 | // 7 - Detects the nullability of a script based on it's opt-in status. |
60 | const int KernelIsolate::kCompileTag = 0; |
61 | const int KernelIsolate::kUpdateSourcesTag = 1; |
62 | const int KernelIsolate::kAcceptTag = 2; |
63 | const int KernelIsolate::kTrainTag = 3; |
64 | const int KernelIsolate::kCompileExpressionTag = 4; |
65 | const int KernelIsolate::kListDependenciesTag = 5; |
66 | const int KernelIsolate::kNotifyIsolateShutdown = 6; |
67 | const int KernelIsolate::kDetectNullabilityTag = 7; |
68 | |
69 | const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME; |
70 | Dart_IsolateGroupCreateCallback KernelIsolate::create_group_callback_ = NULL; |
71 | Monitor* KernelIsolate::monitor_ = new Monitor(); |
72 | KernelIsolate::State KernelIsolate::state_ = KernelIsolate::kNotStarted; |
73 | Isolate* KernelIsolate::isolate_ = NULL; |
74 | Dart_Port KernelIsolate::kernel_port_ = ILLEGAL_PORT; |
75 | |
76 | class RunKernelTask : public ThreadPool::Task { |
77 | public: |
78 | virtual void Run() { |
79 | ASSERT(Isolate::Current() == NULL); |
80 | #ifdef SUPPORT_TIMELINE |
81 | TimelineBeginEndScope tbes(Timeline::GetVMStream(), "KernelIsolateStartup" ); |
82 | #endif // SUPPORT_TIMELINE |
83 | char* error = NULL; |
84 | Isolate* isolate = NULL; |
85 | |
86 | Dart_IsolateGroupCreateCallback create_group_callback = |
87 | KernelIsolate::create_group_callback(); |
88 | ASSERT(create_group_callback != NULL); |
89 | |
90 | // Note: these flags must match those passed to the VM during |
91 | // the app-jit training run (see //utils/kernel-service/BUILD.gn). |
92 | Dart_IsolateFlags api_flags; |
93 | Isolate::FlagsInitialize(&api_flags); |
94 | api_flags.enable_asserts = false; |
95 | #if !defined(DART_PRECOMPILER) |
96 | api_flags.use_field_guards = true; |
97 | #endif |
98 | #if !defined(DART_PRECOMPILER) |
99 | api_flags.use_osr = true; |
100 | #endif |
101 | |
102 | isolate = reinterpret_cast<Isolate*>( |
103 | create_group_callback(KernelIsolate::kName, KernelIsolate::kName, NULL, |
104 | NULL, &api_flags, NULL, &error)); |
105 | if (isolate == NULL) { |
106 | if (FLAG_trace_kernel) { |
107 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n" , |
108 | error); |
109 | } |
110 | free(error); |
111 | error = nullptr; |
112 | KernelIsolate::SetKernelIsolate(NULL); |
113 | KernelIsolate::InitializingFailed(); |
114 | return; |
115 | } |
116 | |
117 | bool got_unwind; |
118 | { |
119 | ASSERT(Isolate::Current() == NULL); |
120 | StartIsolateScope start_scope(isolate); |
121 | got_unwind = RunMain(isolate); |
122 | } |
123 | KernelIsolate::FinishedInitializing(); |
124 | |
125 | if (got_unwind) { |
126 | ShutdownIsolate(reinterpret_cast<uword>(isolate)); |
127 | return; |
128 | } |
129 | |
130 | // isolate_ was set as side effect of create callback. |
131 | ASSERT(KernelIsolate::IsKernelIsolate(isolate)); |
132 | |
133 | isolate->message_handler()->Run(Dart::thread_pool(), NULL, ShutdownIsolate, |
134 | reinterpret_cast<uword>(isolate)); |
135 | } |
136 | |
137 | protected: |
138 | static void ShutdownIsolate(uword parameter) { |
139 | if (FLAG_trace_kernel) { |
140 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n" ); |
141 | } |
142 | Isolate* I = reinterpret_cast<Isolate*>(parameter); |
143 | { |
144 | // Print the error if there is one. This may execute dart code to |
145 | // print the exception object, so we need to use a StartIsolateScope. |
146 | ASSERT(Isolate::Current() == NULL); |
147 | StartIsolateScope start_scope(I); |
148 | Thread* T = Thread::Current(); |
149 | ASSERT(I == T->isolate()); |
150 | I->WaitForOutstandingSpawns(); |
151 | StackZone zone(T); |
152 | HandleScope handle_scope(T); |
153 | Error& error = Error::Handle(Z); |
154 | error = T->sticky_error(); |
155 | if (!error.IsNull() && !error.IsUnwindError()) { |
156 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n" , |
157 | error.ToErrorCString()); |
158 | } |
159 | error = I->sticky_error(); |
160 | if (!error.IsNull() && !error.IsUnwindError()) { |
161 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n" , |
162 | error.ToErrorCString()); |
163 | } |
164 | Dart::RunShutdownCallback(); |
165 | } |
166 | |
167 | ASSERT(KernelIsolate::IsKernelIsolate(I)); |
168 | KernelIsolate::SetLoadPort(ILLEGAL_PORT); |
169 | |
170 | // Shut the isolate down. |
171 | Dart::ShutdownIsolate(I); |
172 | if (FLAG_trace_kernel) { |
173 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n" ); |
174 | } |
175 | KernelIsolate::FinishedExiting(); |
176 | } |
177 | |
178 | bool RunMain(Isolate* I) { |
179 | Thread* T = Thread::Current(); |
180 | ASSERT(I == T->isolate()); |
181 | StackZone zone(T); |
182 | HANDLESCOPE(T); |
183 | // Invoke main which will return the port to which load requests are sent. |
184 | const Library& root_library = |
185 | Library::Handle(Z, I->object_store()->root_library()); |
186 | if (root_library.IsNull()) { |
187 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME |
188 | ": Embedder did not install a script." ); |
189 | // Kernel isolate is not supported by embedder. |
190 | return false; |
191 | } |
192 | ASSERT(!root_library.IsNull()); |
193 | const String& entry_name = String::Handle(Z, String::New("main" )); |
194 | ASSERT(!entry_name.IsNull()); |
195 | const Function& entry = Function::Handle( |
196 | Z, root_library.LookupFunctionAllowPrivate(entry_name)); |
197 | if (entry.IsNull()) { |
198 | // Kernel isolate is not supported by embedder. |
199 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME |
200 | ": Embedder did not provide a main function." ); |
201 | return false; |
202 | } |
203 | ASSERT(!entry.IsNull()); |
204 | const Object& result = Object::Handle( |
205 | Z, DartEntry::InvokeFunction(entry, Object::empty_array())); |
206 | ASSERT(!result.IsNull()); |
207 | if (result.IsError()) { |
208 | // Kernel isolate did not initialize properly. |
209 | if (FLAG_trace_kernel) { |
210 | const Error& error = Error::Cast(result); |
211 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME |
212 | ": Calling main resulted in an error: %s" , |
213 | error.ToErrorCString()); |
214 | } |
215 | if (result.IsUnwindError()) { |
216 | return true; |
217 | } |
218 | return false; |
219 | } |
220 | ASSERT(result.IsReceivePort()); |
221 | const ReceivePort& rp = ReceivePort::Cast(result); |
222 | KernelIsolate::SetLoadPort(rp.Id()); |
223 | return false; |
224 | } |
225 | }; |
226 | |
227 | void KernelIsolate::InitializeState() { |
228 | // Grab the isolate create callback here to avoid race conditions with tests |
229 | // that change this after Dart_Initialize returns. |
230 | if (FLAG_trace_kernel) { |
231 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": InitializeState\n" ); |
232 | } |
233 | create_group_callback_ = Isolate::CreateGroupCallback(); |
234 | if (create_group_callback_ == NULL) { |
235 | KernelIsolate::InitializingFailed(); |
236 | return; |
237 | } |
238 | } |
239 | |
240 | bool KernelIsolate::Start() { |
241 | if (create_group_callback_ == nullptr) { |
242 | if (FLAG_trace_kernel) { |
243 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME |
244 | ": Attempted to start kernel isolate without setting " |
245 | "Dart_InitializeParams property 'start_kernel_isolate' " |
246 | "to true\n" ); |
247 | } |
248 | return false; |
249 | } |
250 | bool start_task = false; |
251 | { |
252 | MonitorLocker ml(monitor_); |
253 | if (state_ == kNotStarted) { |
254 | if (FLAG_trace_kernel) { |
255 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Start\n" ); |
256 | } |
257 | start_task = true; |
258 | state_ = kStarting; |
259 | ml.NotifyAll(); |
260 | } |
261 | } |
262 | bool task_started = true; |
263 | if (start_task) { |
264 | task_started = Dart::thread_pool()->Run<RunKernelTask>(); |
265 | } |
266 | return task_started; |
267 | } |
268 | |
269 | void KernelIsolate::Shutdown() { |
270 | MonitorLocker ml(monitor_); |
271 | while (state_ == kStarting) { |
272 | ml.Wait(); |
273 | } |
274 | if (state_ == kStopped || state_ == kNotStarted) { |
275 | return; |
276 | } |
277 | ASSERT(state_ == kStarted); |
278 | state_ = kStopping; |
279 | ml.NotifyAll(); |
280 | Isolate::KillIfExists(isolate_, Isolate::kInternalKillMsg); |
281 | while (state_ != kStopped) { |
282 | ml.Wait(); |
283 | } |
284 | } |
285 | |
286 | void KernelIsolate::InitCallback(Isolate* I) { |
287 | Thread* T = Thread::Current(); |
288 | ASSERT(I == T->isolate()); |
289 | ASSERT(I != NULL); |
290 | if (!NameEquals(I->name())) { |
291 | // Not kernel isolate. |
292 | return; |
293 | } |
294 | ASSERT(!Exists()); |
295 | if (FLAG_trace_kernel) { |
296 | OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": InitCallback for %s.\n" , |
297 | I->name()); |
298 | } |
299 | SetKernelIsolate(I); |
300 | } |
301 | |
302 | bool KernelIsolate::IsKernelIsolate(const Isolate* isolate) { |
303 | MonitorLocker ml(monitor_); |
304 | return isolate == isolate_; |
305 | } |
306 | |
307 | bool KernelIsolate::IsRunning() { |
308 | MonitorLocker ml(monitor_); |
309 | return (kernel_port_ != ILLEGAL_PORT) && (isolate_ != NULL); |
310 | } |
311 | |
312 | bool KernelIsolate::NameEquals(const char* name) { |
313 | ASSERT(name != NULL); |
314 | return (strcmp(name, DART_KERNEL_ISOLATE_NAME) == 0); |
315 | } |
316 | |
317 | bool KernelIsolate::Exists() { |
318 | MonitorLocker ml(monitor_); |
319 | return isolate_ != NULL; |
320 | } |
321 | |
322 | void KernelIsolate::SetKernelIsolate(Isolate* isolate) { |
323 | MonitorLocker ml(monitor_); |
324 | if (isolate != nullptr) { |
325 | isolate->set_is_kernel_isolate(true); |
326 | } |
327 | isolate_ = isolate; |
328 | ml.NotifyAll(); |
329 | } |
330 | |
331 | void KernelIsolate::SetLoadPort(Dart_Port port) { |
332 | MonitorLocker ml(monitor_); |
333 | kernel_port_ = port; |
334 | ml.NotifyAll(); |
335 | } |
336 | |
337 | void KernelIsolate::FinishedExiting() { |
338 | MonitorLocker ml(monitor_); |
339 | ASSERT(state_ == kStarted || state_ == kStopping); |
340 | state_ = kStopped; |
341 | ml.NotifyAll(); |
342 | } |
343 | |
344 | void KernelIsolate::FinishedInitializing() { |
345 | MonitorLocker ml(monitor_); |
346 | ASSERT(state_ == kStarting); |
347 | state_ = kStarted; |
348 | ml.NotifyAll(); |
349 | } |
350 | |
351 | void KernelIsolate::InitializingFailed() { |
352 | MonitorLocker ml(monitor_); |
353 | ASSERT(state_ == kStarting); |
354 | state_ = kStopped; |
355 | ml.NotifyAll(); |
356 | } |
357 | |
358 | Dart_Port KernelIsolate::WaitForKernelPort() { |
359 | VMTagScope tagScope(Thread::Current(), VMTag::kLoadWaitTagId); |
360 | MonitorLocker ml(monitor_); |
361 | while (state_ == kStarting && (kernel_port_ == ILLEGAL_PORT)) { |
362 | ml.Wait(); |
363 | } |
364 | return kernel_port_; |
365 | } |
366 | |
367 | static Dart_CObject BuildFilesPairs(int source_files_count, |
368 | Dart_SourceFile source_files[]) { |
369 | Dart_CObject files; |
370 | files.type = Dart_CObject_kArray; |
371 | files.value.as_array.length = source_files_count * 2; |
372 | // typedef Dart_CObject* Dart_CObjectPtr; |
373 | Dart_CObject** fileNamePairs = new Dart_CObject*[source_files_count * 2]; |
374 | for (int i = 0; i < source_files_count; i++) { |
375 | Dart_CObject* source_uri = new Dart_CObject(); |
376 | source_uri->type = Dart_CObject_kString; |
377 | source_uri->value.as_string = const_cast<char*>(source_files[i].uri); |
378 | fileNamePairs[i * 2] = source_uri; |
379 | Dart_CObject* source_code = new Dart_CObject(); |
380 | |
381 | if (source_files[i].source != NULL) { |
382 | source_code->type = Dart_CObject_kTypedData; |
383 | source_code->value.as_typed_data.type = Dart_TypedData_kUint8; |
384 | source_code->value.as_typed_data.length = strlen(source_files[i].source); |
385 | source_code->value.as_typed_data.values = |
386 | reinterpret_cast<uint8_t*>(const_cast<char*>(source_files[i].source)); |
387 | } else { |
388 | source_code->type = Dart_CObject_kNull; |
389 | } |
390 | fileNamePairs[(i * 2) + 1] = source_code; |
391 | } |
392 | files.value.as_array.values = fileNamePairs; |
393 | return files; |
394 | } |
395 | |
396 | static void ReleaseFilesPairs(const Dart_CObject& files) { |
397 | for (intptr_t i = 0; i < files.value.as_array.length; i++) { |
398 | delete files.value.as_array.values[i]; |
399 | } |
400 | delete[] files.value.as_array.values; |
401 | } |
402 | |
403 | static void PassThroughFinalizer(void* isolate_callback_data, |
404 | Dart_WeakPersistentHandle handle, |
405 | void* peer) {} |
406 | |
407 | MallocGrowableArray<char*>* KernelIsolate::experimental_flags_ = |
408 | new MallocGrowableArray<char*>(); |
409 | |
410 | void KernelIsolate::AddExperimentalFlag(const char* value) { |
411 | char* save_ptr; // Needed for strtok_r. |
412 | char* temp = Utils::StrDup(value); |
413 | char* token = strtok_r(temp, "," , &save_ptr); |
414 | while (token != NULL) { |
415 | experimental_flags_->Add(Utils::StrDup(token)); |
416 | token = strtok_r(NULL, "," , &save_ptr); |
417 | } |
418 | free(temp); |
419 | } |
420 | |
421 | bool KernelIsolate::GetExperimentalFlag(const char* value) { |
422 | for (const char* str : *experimental_flags_) { |
423 | if (strcmp(str, value) == 0) { |
424 | return true; |
425 | } |
426 | } |
427 | return false; |
428 | } |
429 | |
430 | DEFINE_OPTION_HANDLER(KernelIsolate::AddExperimentalFlag, |
431 | enable_experiment, |
432 | "Comma separated list of experimental features." ); |
433 | |
434 | class KernelCompilationRequest : public ValueObject { |
435 | public: |
436 | KernelCompilationRequest() |
437 | : monitor_(), |
438 | port_(Dart_NewNativePort("kernel-compilation-port" , |
439 | &HandleResponse, |
440 | false)), |
441 | next_(NULL), |
442 | prev_(NULL) { |
443 | ASSERT(port_ != ILLEGAL_PORT); |
444 | RegisterRequest(this); |
445 | result_.status = Dart_KernelCompilationStatus_Unknown; |
446 | result_.error = NULL; |
447 | result_.kernel = NULL; |
448 | result_.kernel_size = 0; |
449 | } |
450 | |
451 | ~KernelCompilationRequest() { |
452 | UnregisterRequest(this); |
453 | Dart_CloseNativePort(port_); |
454 | } |
455 | |
456 | intptr_t setDillData(Dart_CObject** dills_array, |
457 | intptr_t dill_num, |
458 | const uint8_t* buffer, |
459 | intptr_t buffer_size) { |
460 | if (buffer != nullptr) { |
461 | dills_array[dill_num] = new Dart_CObject; |
462 | dills_array[dill_num]->type = Dart_CObject_kExternalTypedData; |
463 | dills_array[dill_num]->value.as_external_typed_data.type = |
464 | Dart_TypedData_kUint8; |
465 | dills_array[dill_num]->value.as_external_typed_data.length = buffer_size; |
466 | dills_array[dill_num]->value.as_external_typed_data.data = |
467 | const_cast<uint8_t*>(buffer); |
468 | dills_array[dill_num]->value.as_external_typed_data.peer = |
469 | const_cast<uint8_t*>(buffer); |
470 | dills_array[dill_num]->value.as_external_typed_data.callback = |
471 | PassThroughFinalizer; |
472 | dill_num++; |
473 | } |
474 | return dill_num; |
475 | } |
476 | |
477 | Dart_KernelCompilationResult SendAndWaitForResponse( |
478 | Dart_Port kernel_port, |
479 | const uint8_t* platform_kernel, |
480 | intptr_t platform_kernel_size, |
481 | const char* expression, |
482 | const Array& definitions, |
483 | const Array& type_definitions, |
484 | char const* library_uri, |
485 | char const* klass, |
486 | bool is_static, |
487 | const MallocGrowableArray<char*>* experimental_flags) { |
488 | Thread* thread = Thread::Current(); |
489 | TransitionNativeToVM transition(thread); |
490 | Dart_CObject tag; |
491 | tag.type = Dart_CObject_kInt32; |
492 | tag.value.as_int32 = KernelIsolate::kCompileExpressionTag; |
493 | |
494 | Dart_CObject send_port; |
495 | send_port.type = Dart_CObject_kSendPort; |
496 | send_port.value.as_send_port.id = port_; |
497 | send_port.value.as_send_port.origin_id = ILLEGAL_PORT; |
498 | |
499 | Dart_CObject dart_platform_kernel; |
500 | if (platform_kernel != NULL) { |
501 | dart_platform_kernel.type = Dart_CObject_kExternalTypedData; |
502 | dart_platform_kernel.value.as_external_typed_data.type = |
503 | Dart_TypedData_kUint8; |
504 | dart_platform_kernel.value.as_external_typed_data.length = |
505 | platform_kernel_size; |
506 | dart_platform_kernel.value.as_external_typed_data.data = |
507 | const_cast<uint8_t*>(platform_kernel); |
508 | dart_platform_kernel.value.as_external_typed_data.peer = |
509 | const_cast<uint8_t*>(platform_kernel); |
510 | dart_platform_kernel.value.as_external_typed_data.callback = |
511 | PassThroughFinalizer; |
512 | } else { |
513 | // If NULL, the kernel service looks up the platform dill file |
514 | // next to the executable. |
515 | dart_platform_kernel.type = Dart_CObject_kNull; |
516 | } |
517 | |
518 | Dart_CObject expression_object; |
519 | expression_object.type = Dart_CObject_kString; |
520 | expression_object.value.as_string = const_cast<char*>(expression); |
521 | |
522 | Dart_CObject definitions_object; |
523 | intptr_t num_definitions = definitions.Length(); |
524 | definitions_object.type = Dart_CObject_kArray; |
525 | definitions_object.value.as_array.length = num_definitions; |
526 | |
527 | Dart_CObject** definitions_array = new Dart_CObject*[num_definitions]; |
528 | for (intptr_t i = 0; i < num_definitions; ++i) { |
529 | definitions_array[i] = new Dart_CObject; |
530 | definitions_array[i]->type = Dart_CObject_kString; |
531 | definitions_array[i]->value.as_string = const_cast<char*>( |
532 | String::CheckedHandle(thread->zone(), definitions.At(i)).ToCString()); |
533 | } |
534 | definitions_object.value.as_array.values = definitions_array; |
535 | |
536 | Dart_CObject type_definitions_object; |
537 | intptr_t num_type_definitions = type_definitions.Length(); |
538 | type_definitions_object.type = Dart_CObject_kArray; |
539 | type_definitions_object.value.as_array.length = num_type_definitions; |
540 | |
541 | Dart_CObject** type_definitions_array = |
542 | new Dart_CObject*[num_type_definitions]; |
543 | for (intptr_t i = 0; i < num_type_definitions; ++i) { |
544 | type_definitions_array[i] = new Dart_CObject; |
545 | type_definitions_array[i]->type = Dart_CObject_kString; |
546 | type_definitions_array[i]->value.as_string = const_cast<char*>( |
547 | String::CheckedHandle(thread->zone(), type_definitions.At(i)) |
548 | .ToCString()); |
549 | } |
550 | type_definitions_object.value.as_array.values = type_definitions_array; |
551 | |
552 | Dart_CObject library_uri_object; |
553 | library_uri_object.type = Dart_CObject_kString; |
554 | library_uri_object.value.as_string = const_cast<char*>(library_uri); |
555 | |
556 | Dart_CObject class_object; |
557 | if (klass != NULL) { |
558 | class_object.type = Dart_CObject_kString; |
559 | class_object.value.as_string = const_cast<char*>(klass); |
560 | } else { |
561 | class_object.type = Dart_CObject_kNull; |
562 | } |
563 | |
564 | Dart_CObject is_static_object; |
565 | is_static_object.type = Dart_CObject_kBool; |
566 | is_static_object.value.as_bool = is_static; |
567 | |
568 | Isolate* isolate = |
569 | Thread::Current() != NULL ? Thread::Current()->isolate() : NULL; |
570 | ASSERT(isolate != NULL); |
571 | Dart_CObject isolate_id; |
572 | isolate_id.type = Dart_CObject_kInt64; |
573 | isolate_id.value.as_int64 = |
574 | isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0; |
575 | |
576 | IsolateGroupSource* source = Isolate::Current()->source(); |
577 | intptr_t num_dills = 0; |
578 | if (source->kernel_buffer != nullptr) { |
579 | num_dills++; |
580 | } |
581 | if (source->script_kernel_buffer != nullptr) { |
582 | num_dills++; |
583 | } |
584 | Array& loaded_blobs = Array::Handle(); |
585 | if (source->loaded_blobs_ != nullptr) { |
586 | loaded_blobs = source->loaded_blobs_; |
587 | WeakProperty& weak_property = WeakProperty::Handle(); |
588 | for (intptr_t i = 0; i < loaded_blobs.Length(); i++) { |
589 | weak_property ^= loaded_blobs.At(i); |
590 | if (weak_property.key() != ExternalTypedData::null()) { |
591 | num_dills++; |
592 | } |
593 | } |
594 | } |
595 | |
596 | Dart_CObject dills_object; |
597 | dills_object.type = Dart_CObject_kArray; |
598 | dills_object.value.as_array.length = num_dills; |
599 | |
600 | Dart_CObject** dills_array = new Dart_CObject*[num_dills]; |
601 | intptr_t dill_num = 0; |
602 | dill_num = setDillData(dills_array, dill_num, source->kernel_buffer, |
603 | source->kernel_buffer_size); |
604 | dill_num = setDillData(dills_array, dill_num, source->script_kernel_buffer, |
605 | source->script_kernel_size); |
606 | if (!loaded_blobs.IsNull()) { |
607 | WeakProperty& weak_property = WeakProperty::Handle(); |
608 | for (intptr_t i = 0; i < loaded_blobs.Length(); i++) { |
609 | weak_property ^= loaded_blobs.At(i); |
610 | if (weak_property.key() != ExternalTypedData::null()) { |
611 | ExternalTypedData& externalTypedData = ExternalTypedData::Handle( |
612 | thread->zone(), ExternalTypedData::RawCast(weak_property.key())); |
613 | NoSafepointScope no_safepoint(thread); |
614 | const uint8_t* data = const_cast<uint8_t*>( |
615 | reinterpret_cast<uint8_t*>(externalTypedData.DataAddr(0))); |
616 | dill_num = setDillData(dills_array, dill_num, data, |
617 | externalTypedData.Length()); |
618 | } |
619 | } |
620 | } |
621 | dills_object.value.as_array.values = dills_array; |
622 | |
623 | Dart_CObject num_blob_loads; |
624 | num_blob_loads.type = Dart_CObject_kInt64; |
625 | num_blob_loads.value.as_int64 = source->num_blob_loads_; |
626 | |
627 | Dart_CObject suppress_warnings; |
628 | suppress_warnings.type = Dart_CObject_kBool; |
629 | suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings; |
630 | |
631 | Dart_CObject enable_asserts; |
632 | enable_asserts.type = Dart_CObject_kBool; |
633 | enable_asserts.value.as_bool = |
634 | isolate != NULL ? isolate->asserts() : FLAG_enable_asserts; |
635 | |
636 | intptr_t num_experimental_flags = experimental_flags->length(); |
637 | Dart_CObject** experimental_flags_array = |
638 | new Dart_CObject*[num_experimental_flags]; |
639 | for (intptr_t i = 0; i < num_experimental_flags; ++i) { |
640 | experimental_flags_array[i] = new Dart_CObject; |
641 | experimental_flags_array[i]->type = Dart_CObject_kString; |
642 | experimental_flags_array[i]->value.as_string = (*experimental_flags)[i]; |
643 | } |
644 | Dart_CObject experimental_flags_object; |
645 | experimental_flags_object.type = Dart_CObject_kArray; |
646 | experimental_flags_object.value.as_array.values = experimental_flags_array; |
647 | experimental_flags_object.value.as_array.length = num_experimental_flags; |
648 | |
649 | Dart_CObject bytecode; |
650 | bytecode.type = Dart_CObject_kBool; |
651 | bytecode.value.as_bool = |
652 | FLAG_enable_interpreter || FLAG_use_bytecode_compiler; |
653 | |
654 | Dart_CObject message; |
655 | message.type = Dart_CObject_kArray; |
656 | Dart_CObject* message_arr[] = {&tag, |
657 | &send_port, |
658 | &isolate_id, |
659 | &dart_platform_kernel, |
660 | &expression_object, |
661 | &definitions_object, |
662 | &type_definitions_object, |
663 | &library_uri_object, |
664 | &class_object, |
665 | &is_static_object, |
666 | &dills_object, |
667 | &num_blob_loads, |
668 | &suppress_warnings, |
669 | &enable_asserts, |
670 | &experimental_flags_object, |
671 | &bytecode}; |
672 | message.value.as_array.values = message_arr; |
673 | message.value.as_array.length = ARRAY_SIZE(message_arr); |
674 | |
675 | { |
676 | TransitionVMToNative transition(thread); |
677 | |
678 | // Send the message. |
679 | Dart_PostCObject(kernel_port, &message); |
680 | |
681 | // Wait for reply to arrive. |
682 | VMTagScope tagScope(thread, VMTag::kLoadWaitTagId); |
683 | MonitorLocker ml(&monitor_); |
684 | while (result_.status == Dart_KernelCompilationStatus_Unknown) { |
685 | ml.Wait(); |
686 | } |
687 | } |
688 | |
689 | for (intptr_t i = 0; i < num_definitions; ++i) { |
690 | delete definitions_array[i]; |
691 | } |
692 | delete[] definitions_array; |
693 | |
694 | for (intptr_t i = 0; i < num_type_definitions; ++i) { |
695 | delete type_definitions_array[i]; |
696 | } |
697 | delete[] type_definitions_array; |
698 | |
699 | for (intptr_t i = 0; i < num_dills; ++i) { |
700 | delete dills_array[i]; |
701 | } |
702 | delete[] dills_array; |
703 | |
704 | for (intptr_t i = 0; i < num_experimental_flags; ++i) { |
705 | delete experimental_flags_array[i]; |
706 | } |
707 | delete[] experimental_flags_array; |
708 | |
709 | return result_; |
710 | } |
711 | |
712 | Dart_KernelCompilationResult SendAndWaitForResponse( |
713 | int request_tag, |
714 | Dart_Port kernel_port, |
715 | const char* script_uri, |
716 | const uint8_t* platform_kernel, |
717 | intptr_t platform_kernel_size, |
718 | int source_files_count, |
719 | Dart_SourceFile source_files[], |
720 | bool incremental_compile, |
721 | const char* package_config, |
722 | const char* multiroot_filepaths, |
723 | const char* multiroot_scheme, |
724 | const MallocGrowableArray<char*>* experimental_flags, |
725 | const char* original_working_directory) { |
726 | // Build the message for the Kernel isolate. |
727 | // tag is used to specify which operation the frontend should perform. |
728 | Dart_CObject tag; |
729 | tag.type = Dart_CObject_kInt32; |
730 | tag.value.as_int32 = request_tag; |
731 | |
732 | Dart_CObject send_port; |
733 | send_port.type = Dart_CObject_kSendPort; |
734 | send_port.value.as_send_port.id = port_; |
735 | send_port.value.as_send_port.origin_id = ILLEGAL_PORT; |
736 | |
737 | Dart_CObject uri; |
738 | if (script_uri != NULL) { |
739 | uri.type = Dart_CObject_kString; |
740 | uri.value.as_string = const_cast<char*>(script_uri); |
741 | } else { |
742 | uri.type = Dart_CObject_kNull; |
743 | } |
744 | |
745 | Dart_CObject dart_platform_kernel; |
746 | if (platform_kernel != NULL) { |
747 | dart_platform_kernel.type = Dart_CObject_kExternalTypedData; |
748 | dart_platform_kernel.value.as_external_typed_data.type = |
749 | Dart_TypedData_kUint8; |
750 | dart_platform_kernel.value.as_external_typed_data.length = |
751 | platform_kernel_size; |
752 | dart_platform_kernel.value.as_external_typed_data.data = |
753 | const_cast<uint8_t*>(platform_kernel); |
754 | dart_platform_kernel.value.as_external_typed_data.peer = |
755 | const_cast<uint8_t*>(platform_kernel); |
756 | dart_platform_kernel.value.as_external_typed_data.callback = |
757 | PassThroughFinalizer; |
758 | } else { |
759 | // If NULL, the kernel service looks up the platform dill file |
760 | // next to the executable. |
761 | dart_platform_kernel.type = Dart_CObject_kNull; |
762 | } |
763 | |
764 | Dart_CObject dart_incremental; |
765 | dart_incremental.type = Dart_CObject_kBool; |
766 | dart_incremental.value.as_bool = incremental_compile; |
767 | |
768 | // TODO(aam): Assert that isolate exists once we move CompileAndReadScript |
769 | // compilation logic out of CreateIsolateAndSetupHelper and into |
770 | // IsolateSetupHelper in main.cc. |
771 | Isolate* isolate = |
772 | Thread::Current() != NULL ? Thread::Current()->isolate() : NULL; |
773 | if (incremental_compile) { |
774 | ASSERT(isolate != NULL); |
775 | } |
776 | Dart_CObject isolate_id; |
777 | isolate_id.type = Dart_CObject_kInt64; |
778 | isolate_id.value.as_int64 = |
779 | isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0; |
780 | |
781 | Dart_CObject message; |
782 | message.type = Dart_CObject_kArray; |
783 | |
784 | Dart_CObject files = BuildFilesPairs(source_files_count, source_files); |
785 | |
786 | Dart_CObject suppress_warnings; |
787 | suppress_warnings.type = Dart_CObject_kBool; |
788 | suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings; |
789 | |
790 | Dart_CObject enable_asserts; |
791 | enable_asserts.type = Dart_CObject_kBool; |
792 | enable_asserts.value.as_bool = |
793 | isolate != NULL ? isolate->asserts() : FLAG_enable_asserts; |
794 | |
795 | Dart_CObject null_safety; |
796 | null_safety.type = Dart_CObject_kInt32; |
797 | null_safety.value.as_int32 = |
798 | (isolate != NULL) ? (isolate->null_safety() ? kNullSafetyOptionStrong |
799 | : kNullSafetyOptionWeak) |
800 | : FLAG_sound_null_safety; |
801 | |
802 | intptr_t num_experimental_flags = experimental_flags->length(); |
803 | Dart_CObject** experimental_flags_array = |
804 | new Dart_CObject*[num_experimental_flags]; |
805 | for (intptr_t i = 0; i < num_experimental_flags; ++i) { |
806 | experimental_flags_array[i] = new Dart_CObject; |
807 | experimental_flags_array[i]->type = Dart_CObject_kString; |
808 | experimental_flags_array[i]->value.as_string = (*experimental_flags)[i]; |
809 | } |
810 | Dart_CObject experimental_flags_object; |
811 | experimental_flags_object.type = Dart_CObject_kArray; |
812 | experimental_flags_object.value.as_array.values = experimental_flags_array; |
813 | experimental_flags_object.value.as_array.length = num_experimental_flags; |
814 | |
815 | Dart_CObject bytecode; |
816 | bytecode.type = Dart_CObject_kBool; |
817 | bytecode.value.as_bool = |
818 | FLAG_enable_interpreter || FLAG_use_bytecode_compiler; |
819 | |
820 | Dart_CObject package_config_uri; |
821 | if (package_config != NULL) { |
822 | package_config_uri.type = Dart_CObject_kString; |
823 | package_config_uri.value.as_string = const_cast<char*>(package_config); |
824 | } else { |
825 | package_config_uri.type = Dart_CObject_kNull; |
826 | } |
827 | |
828 | Dart_CObject multiroot_filepaths_object; |
829 | { |
830 | const char* filepaths = multiroot_filepaths != NULL |
831 | ? multiroot_filepaths |
832 | : FLAG_kernel_multiroot_filepaths; |
833 | if (filepaths != NULL) { |
834 | multiroot_filepaths_object.type = Dart_CObject_kString; |
835 | multiroot_filepaths_object.value.as_string = |
836 | const_cast<char*>(filepaths); |
837 | } else { |
838 | multiroot_filepaths_object.type = Dart_CObject_kNull; |
839 | } |
840 | } |
841 | |
842 | Dart_CObject multiroot_scheme_object; |
843 | { |
844 | const char* scheme = multiroot_scheme != NULL |
845 | ? multiroot_scheme |
846 | : FLAG_kernel_multiroot_scheme; |
847 | if (scheme != NULL) { |
848 | multiroot_scheme_object.type = Dart_CObject_kString; |
849 | multiroot_scheme_object.value.as_string = const_cast<char*>(scheme); |
850 | } else { |
851 | multiroot_scheme_object.type = Dart_CObject_kNull; |
852 | } |
853 | } |
854 | |
855 | Dart_CObject original_working_directory_object; |
856 | { |
857 | if (original_working_directory != NULL) { |
858 | original_working_directory_object.type = Dart_CObject_kString; |
859 | original_working_directory_object.value.as_string = |
860 | const_cast<char*>(original_working_directory); |
861 | } else { |
862 | original_working_directory_object.type = Dart_CObject_kNull; |
863 | } |
864 | } |
865 | |
866 | Dart_CObject* message_arr[] = {&tag, |
867 | &send_port, |
868 | &uri, |
869 | &dart_platform_kernel, |
870 | &dart_incremental, |
871 | &null_safety, |
872 | &isolate_id, |
873 | &files, |
874 | &suppress_warnings, |
875 | &enable_asserts, |
876 | &experimental_flags_object, |
877 | &bytecode, |
878 | &package_config_uri, |
879 | &multiroot_filepaths_object, |
880 | &multiroot_scheme_object, |
881 | &original_working_directory_object}; |
882 | message.value.as_array.values = message_arr; |
883 | message.value.as_array.length = ARRAY_SIZE(message_arr); |
884 | // Send the message. |
885 | Dart_PostCObject(kernel_port, &message); |
886 | |
887 | ReleaseFilesPairs(files); |
888 | |
889 | // Wait for reply to arrive. |
890 | VMTagScope tagScope(Thread::Current(), VMTag::kLoadWaitTagId); |
891 | MonitorLocker ml(&monitor_); |
892 | while (result_.status == Dart_KernelCompilationStatus_Unknown) { |
893 | ml.Wait(); |
894 | } |
895 | |
896 | for (intptr_t i = 0; i < num_experimental_flags; ++i) { |
897 | delete experimental_flags_array[i]; |
898 | } |
899 | delete[] experimental_flags_array; |
900 | |
901 | return result_; |
902 | } |
903 | |
904 | private: |
905 | void LoadKernelFromResponse(Dart_CObject* response) { |
906 | ASSERT((response->type == Dart_CObject_kTypedData) || |
907 | (response->type == Dart_CObject_kBool) || |
908 | (response->type == Dart_CObject_kNull)); |
909 | |
910 | if (response->type == Dart_CObject_kNull) { |
911 | return; |
912 | } |
913 | if (response->type == Dart_CObject_kBool) { |
914 | result_.null_safety = response->value.as_bool; |
915 | return; |
916 | } |
917 | |
918 | ASSERT(response->value.as_typed_data.type == Dart_TypedData_kUint8); |
919 | result_.kernel_size = response->value.as_typed_data.length; |
920 | result_.kernel = static_cast<uint8_t*>(malloc(result_.kernel_size)); |
921 | memmove(result_.kernel, response->value.as_typed_data.values, |
922 | result_.kernel_size); |
923 | } |
924 | |
925 | // Possible responses from the Kernel isolate: |
926 | // |
927 | // [Ok, Uint8List KernelBinary] |
928 | // [Error, String error, Uint8List KernelBinary] |
929 | // [Crash, String error] |
930 | // |
931 | void HandleResponseImpl(Dart_CObject* message) { |
932 | ASSERT(message->type == Dart_CObject_kArray); |
933 | ASSERT(message->value.as_array.length >= 1); |
934 | |
935 | Dart_CObject** response = message->value.as_array.values; |
936 | |
937 | MonitorLocker ml(&monitor_); |
938 | |
939 | ASSERT(response[0]->type == Dart_CObject_kInt32); |
940 | result_.status = static_cast<Dart_KernelCompilationStatus>( |
941 | message->value.as_array.values[0]->value.as_int32); |
942 | |
943 | if (result_.status == Dart_KernelCompilationStatus_Ok) { |
944 | LoadKernelFromResponse(response[1]); |
945 | } else { |
946 | if (result_.status == Dart_KernelCompilationStatus_Error) { |
947 | LoadKernelFromResponse(response[2]); |
948 | } |
949 | // This is an error. |
950 | ASSERT(response[1]->type == Dart_CObject_kString); |
951 | result_.error = Utils::StrDup(response[1]->value.as_string); |
952 | } |
953 | ml.Notify(); |
954 | } |
955 | |
956 | static void HandleResponse(Dart_Port port, Dart_CObject* message) { |
957 | MonitorLocker locker(requests_monitor_); |
958 | KernelCompilationRequest* rq = FindRequestLocked(port); |
959 | if (rq == NULL) { |
960 | return; |
961 | } |
962 | rq->HandleResponseImpl(message); |
963 | } |
964 | |
965 | static void RegisterRequest(KernelCompilationRequest* rq) { |
966 | MonitorLocker locker(requests_monitor_); |
967 | rq->next_ = requests_; |
968 | if (requests_ != NULL) { |
969 | requests_->prev_ = rq; |
970 | } |
971 | requests_ = rq; |
972 | } |
973 | |
974 | static void UnregisterRequest(KernelCompilationRequest* rq) { |
975 | MonitorLocker locker(requests_monitor_); |
976 | if (rq->next_ != NULL) { |
977 | rq->next_->prev_ = rq->prev_; |
978 | } |
979 | if (rq->prev_ != NULL) { |
980 | rq->prev_->next_ = rq->next_; |
981 | } else { |
982 | requests_ = rq->next_; |
983 | } |
984 | } |
985 | |
986 | // Note: Caller must hold requests_monitor_. |
987 | static KernelCompilationRequest* FindRequestLocked(Dart_Port port) { |
988 | for (KernelCompilationRequest* rq = requests_; rq != NULL; rq = rq->next_) { |
989 | if (rq->port_ == port) { |
990 | return rq; |
991 | } |
992 | } |
993 | return NULL; |
994 | } |
995 | |
996 | // This monitor must be held whenever linked list of requests is accessed. |
997 | static Monitor* requests_monitor_; |
998 | |
999 | // Linked list of all active requests. Used to find a request by port number. |
1000 | // Guarded by requests_monitor_ lock. |
1001 | static KernelCompilationRequest* requests_; |
1002 | |
1003 | Monitor monitor_; |
1004 | Dart_Port port_; |
1005 | |
1006 | // Linked list of active requests. Guarded by requests_monitor_ lock. |
1007 | KernelCompilationRequest* next_; |
1008 | KernelCompilationRequest* prev_; |
1009 | |
1010 | Dart_KernelCompilationResult result_ = {}; |
1011 | }; |
1012 | |
1013 | Monitor* KernelCompilationRequest::requests_monitor_ = new Monitor(); |
1014 | KernelCompilationRequest* KernelCompilationRequest::requests_ = NULL; |
1015 | |
1016 | Dart_KernelCompilationResult KernelIsolate::CompileToKernel( |
1017 | const char* script_uri, |
1018 | const uint8_t* platform_kernel, |
1019 | intptr_t platform_kernel_size, |
1020 | int source_file_count, |
1021 | Dart_SourceFile source_files[], |
1022 | bool incremental_compile, |
1023 | const char* package_config, |
1024 | const char* multiroot_filepaths, |
1025 | const char* multiroot_scheme) { |
1026 | // Start the kernel Isolate if it is not already running. |
1027 | if (!Start()) { |
1028 | Dart_KernelCompilationResult result = {}; |
1029 | result.status = Dart_KernelCompilationStatus_Unknown; |
1030 | result.error = Utils::StrDup("Error while starting Kernel isolate task" ); |
1031 | return result; |
1032 | } |
1033 | |
1034 | // This must be the main script to be loaded. Wait for Kernel isolate |
1035 | // to finish initialization. |
1036 | Dart_Port kernel_port = WaitForKernelPort(); |
1037 | if (kernel_port == ILLEGAL_PORT) { |
1038 | Dart_KernelCompilationResult result = {}; |
1039 | result.status = Dart_KernelCompilationStatus_Unknown; |
1040 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1041 | return result; |
1042 | } |
1043 | |
1044 | KernelCompilationRequest request; |
1045 | return request.SendAndWaitForResponse( |
1046 | kCompileTag, kernel_port, script_uri, platform_kernel, |
1047 | platform_kernel_size, source_file_count, source_files, |
1048 | incremental_compile, package_config, multiroot_filepaths, |
1049 | multiroot_scheme, experimental_flags_, NULL); |
1050 | } |
1051 | |
1052 | bool KernelIsolate::DetectNullSafety(const char* script_uri, |
1053 | const char* package_config, |
1054 | const char* original_working_directory) { |
1055 | // Start the kernel Isolate if it is not already running. |
1056 | if (!Start()) { |
1057 | Dart_KernelCompilationResult result = {}; |
1058 | result.status = Dart_KernelCompilationStatus_Unknown; |
1059 | result.error = Utils::StrDup("Error while starting Kernel isolate task" ); |
1060 | return false; |
1061 | } |
1062 | // Wait for Kernel isolate to finish initialization. |
1063 | Dart_Port kernel_port = WaitForKernelPort(); |
1064 | if (kernel_port == ILLEGAL_PORT) { |
1065 | Dart_KernelCompilationResult result = {}; |
1066 | result.status = Dart_KernelCompilationStatus_Unknown; |
1067 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1068 | return false; |
1069 | } |
1070 | KernelCompilationRequest request; |
1071 | Dart_KernelCompilationResult result = request.SendAndWaitForResponse( |
1072 | kDetectNullabilityTag, kernel_port, script_uri, nullptr, -1, 0, nullptr, |
1073 | false, package_config, nullptr, nullptr, experimental_flags_, |
1074 | original_working_directory); |
1075 | return result.null_safety; |
1076 | } |
1077 | |
1078 | Dart_KernelCompilationResult KernelIsolate::ListDependencies() { |
1079 | Dart_Port kernel_port = WaitForKernelPort(); |
1080 | if (kernel_port == ILLEGAL_PORT) { |
1081 | Dart_KernelCompilationResult result = {}; |
1082 | result.status = Dart_KernelCompilationStatus_Unknown; |
1083 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1084 | return result; |
1085 | } |
1086 | |
1087 | KernelCompilationRequest request; |
1088 | return request.SendAndWaitForResponse(kListDependenciesTag, kernel_port, NULL, |
1089 | NULL, 0, 0, NULL, false, NULL, NULL, |
1090 | NULL, experimental_flags_, NULL); |
1091 | } |
1092 | |
1093 | Dart_KernelCompilationResult KernelIsolate::AcceptCompilation() { |
1094 | // This must be the main script to be loaded. Wait for Kernel isolate |
1095 | // to finish initialization. |
1096 | Dart_Port kernel_port = WaitForKernelPort(); |
1097 | if (kernel_port == ILLEGAL_PORT) { |
1098 | Dart_KernelCompilationResult result = {}; |
1099 | result.status = Dart_KernelCompilationStatus_Unknown; |
1100 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1101 | return result; |
1102 | } |
1103 | |
1104 | KernelCompilationRequest request; |
1105 | return request.SendAndWaitForResponse(kAcceptTag, kernel_port, NULL, NULL, 0, |
1106 | 0, NULL, true, NULL, NULL, NULL, |
1107 | experimental_flags_, NULL); |
1108 | } |
1109 | |
1110 | Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel( |
1111 | const uint8_t* platform_kernel, |
1112 | intptr_t platform_kernel_size, |
1113 | const char* expression, |
1114 | const Array& definitions, |
1115 | const Array& type_definitions, |
1116 | const char* library_url, |
1117 | const char* klass, |
1118 | bool is_static) { |
1119 | Dart_Port kernel_port = WaitForKernelPort(); |
1120 | if (kernel_port == ILLEGAL_PORT) { |
1121 | Dart_KernelCompilationResult result = {}; |
1122 | result.status = Dart_KernelCompilationStatus_Unknown; |
1123 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1124 | return result; |
1125 | } |
1126 | |
1127 | TransitionVMToNative transition(Thread::Current()); |
1128 | KernelCompilationRequest request; |
1129 | ASSERT(is_static || (klass != nullptr)); |
1130 | return request.SendAndWaitForResponse( |
1131 | kernel_port, platform_kernel, platform_kernel_size, expression, |
1132 | definitions, type_definitions, library_url, klass, is_static, |
1133 | experimental_flags_); |
1134 | } |
1135 | |
1136 | Dart_KernelCompilationResult KernelIsolate::UpdateInMemorySources( |
1137 | int source_files_count, |
1138 | Dart_SourceFile source_files[]) { |
1139 | // This must be the main script to be loaded. Wait for Kernel isolate |
1140 | // to finish initialization. |
1141 | Dart_Port kernel_port = WaitForKernelPort(); |
1142 | if (kernel_port == ILLEGAL_PORT) { |
1143 | Dart_KernelCompilationResult result = {}; |
1144 | result.status = Dart_KernelCompilationStatus_Unknown; |
1145 | result.error = Utils::StrDup("Error while initializing Kernel isolate" ); |
1146 | return result; |
1147 | } |
1148 | |
1149 | KernelCompilationRequest request; |
1150 | return request.SendAndWaitForResponse( |
1151 | kUpdateSourcesTag, kernel_port, NULL, NULL, 0, source_files_count, |
1152 | source_files, true, NULL, NULL, NULL, experimental_flags_, NULL); |
1153 | } |
1154 | |
1155 | void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) { |
1156 | if (!KernelIsolate::IsRunning()) { |
1157 | return; |
1158 | } |
1159 | Dart_Port kernel_port = WaitForKernelPort(); |
1160 | if (kernel_port == ILLEGAL_PORT) { |
1161 | return; |
1162 | } |
1163 | |
1164 | Dart_CObject tag; |
1165 | tag.type = Dart_CObject_kInt32; |
1166 | tag.value.as_int32 = KernelIsolate::kNotifyIsolateShutdown; |
1167 | |
1168 | Dart_CObject isolate_id; |
1169 | isolate_id.type = Dart_CObject_kInt64; |
1170 | isolate_id.value.as_int64 = |
1171 | isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0; |
1172 | |
1173 | Dart_CObject message; |
1174 | message.type = Dart_CObject_kArray; |
1175 | Dart_CObject* message_arr[] = {&tag, &isolate_id}; |
1176 | message.value.as_array.values = message_arr; |
1177 | message.value.as_array.length = ARRAY_SIZE(message_arr); |
1178 | // Send the message. |
1179 | Dart_PostCObject(kernel_port, &message); |
1180 | } |
1181 | |
1182 | } // namespace dart |
1183 | |
1184 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
1185 | |