1// Copyright (c) 2013, 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 <memory>
6#include <utility>
7
8#include "vm/dart.h"
9
10#include "vm/clustered_snapshot.h"
11#include "vm/code_observers.h"
12#include "vm/compiler/runtime_offsets_extracted.h"
13#include "vm/compiler/runtime_offsets_list.h"
14#include "vm/cpu.h"
15#include "vm/dart_api_state.h"
16#include "vm/dart_entry.h"
17#include "vm/debugger.h"
18#include "vm/flags.h"
19#include "vm/handles.h"
20#include "vm/heap/become.h"
21#include "vm/heap/freelist.h"
22#include "vm/heap/heap.h"
23#include "vm/heap/pointer_block.h"
24#include "vm/isolate.h"
25#include "vm/isolate_reload.h"
26#include "vm/kernel_isolate.h"
27#include "vm/malloc_hooks.h"
28#include "vm/message_handler.h"
29#include "vm/metrics.h"
30#include "vm/native_entry.h"
31#include "vm/object.h"
32#include "vm/object_id_ring.h"
33#include "vm/object_store.h"
34#include "vm/port.h"
35#include "vm/profiler.h"
36#include "vm/reverse_pc_lookup_cache.h"
37#include "vm/service_isolate.h"
38#include "vm/simulator.h"
39#include "vm/snapshot.h"
40#include "vm/stack_frame.h"
41#include "vm/stub_code.h"
42#include "vm/symbols.h"
43#include "vm/thread_interrupter.h"
44#include "vm/thread_pool.h"
45#include "vm/timeline.h"
46#include "vm/virtual_memory.h"
47#include "vm/zone.h"
48
49namespace dart {
50
51DECLARE_FLAG(bool, print_class_table);
52DEFINE_FLAG(bool, keep_code, false, "Keep deoptimized code for profiling.");
53DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
54DECLARE_FLAG(bool, strong);
55
56#if defined(DART_PRECOMPILED_RUNTIME)
57DEFINE_FLAG(bool, print_llvm_constant_pool, false, "Print LLVM constant pool");
58#endif
59
60Isolate* Dart::vm_isolate_ = NULL;
61int64_t Dart::start_time_micros_ = 0;
62ThreadPool* Dart::thread_pool_ = NULL;
63DebugInfo* Dart::pprof_symbol_generator_ = NULL;
64ReadOnlyHandles* Dart::predefined_handles_ = NULL;
65Snapshot::Kind Dart::vm_snapshot_kind_ = Snapshot::kInvalid;
66Dart_ThreadExitCallback Dart::thread_exit_callback_ = NULL;
67Dart_FileOpenCallback Dart::file_open_callback_ = NULL;
68Dart_FileReadCallback Dart::file_read_callback_ = NULL;
69Dart_FileWriteCallback Dart::file_write_callback_ = NULL;
70Dart_FileCloseCallback Dart::file_close_callback_ = NULL;
71Dart_EntropySource Dart::entropy_source_callback_ = NULL;
72
73// Structure for managing read-only global handles allocation used for
74// creating global read-only handles that are pre created and initialized
75// for use across all isolates. Having these global pre created handles
76// stored in the vm isolate ensures that we don't constantly create and
77// destroy handles for read-only objects referred in the VM code
78// (e.g: symbols, null object, empty array etc.)
79// The ReadOnlyHandles C++ Wrapper around VMHandles which is a ValueObject is
80// to ensure that the handles area is not trashed by automatic running of C++
81// static destructors when 'exit()" is called by any isolate. There might be
82// other isolates running at the same time and trashing the handles area will
83// have unintended consequences.
84class ReadOnlyHandles {
85 public:
86 ReadOnlyHandles() {}
87
88 private:
89 VMHandles handles_;
90 LocalHandles api_handles_;
91
92 friend class Dart;
93 DISALLOW_COPY_AND_ASSIGN(ReadOnlyHandles);
94};
95
96static void CheckOffsets() {
97#if !defined(IS_SIMARM_X64)
98 // These offsets are embedded in precompiled instructions. We need the
99 // compiler and the runtime to agree.
100 bool ok = true;
101#define CHECK_OFFSET(expr, offset) \
102 if ((expr) != (offset)) { \
103 OS::PrintErr("%s got %" Pd ", %s expected %" Pd "\n", #expr, \
104 static_cast<intptr_t>(expr), #offset, \
105 static_cast<intptr_t>(offset)); \
106 ok = false; \
107 }
108
109#if defined(DART_PRECOMPILED_RUNTIME)
110#define CHECK_FIELD(Class, Name) \
111 CHECK_OFFSET(Class::Name(), AOT_##Class##_##Name);
112#define CHECK_ARRAY(Class, Name) \
113 CHECK_OFFSET(Class::ArrayTraits::elements_start_offset(), \
114 AOT_##Class##_elements_start_offset); \
115 CHECK_OFFSET(Class::ArrayTraits::kElementSize, AOT_##Class##_element_size)
116#define CHECK_SIZEOF(Class, Name, What) \
117 CHECK_OFFSET(sizeof(What), AOT_##Class##_##Name);
118#define CHECK_RANGE(Class, Getter, Type, First, Last, Filter) \
119 for (intptr_t i = static_cast<intptr_t>(First); \
120 i <= static_cast<intptr_t>(Last); i++) { \
121 if (Filter(static_cast<Type>(i))) { \
122 CHECK_OFFSET(Class::Getter(static_cast<Type>(i)), \
123 AOT_##Class##_##Getter[i]); \
124 } \
125 }
126#define CHECK_CONSTANT(Class, Name) \
127 CHECK_OFFSET(Class::Name, AOT_##Class##_##Name);
128#else
129#define CHECK_FIELD(Class, Name) CHECK_OFFSET(Class::Name(), Class##_##Name);
130#define CHECK_ARRAY(Class, Name) \
131 CHECK_OFFSET(Class::ArrayTraits::elements_start_offset(), \
132 Class##_elements_start_offset); \
133 CHECK_OFFSET(Class::ArrayTraits::kElementSize, Class##_element_size);
134#define CHECK_SIZEOF(Class, Name, What) \
135 CHECK_OFFSET(sizeof(What), Class##_##Name);
136#define CHECK_RANGE(Class, Getter, Type, First, Last, Filter) \
137 for (intptr_t i = static_cast<intptr_t>(First); \
138 i <= static_cast<intptr_t>(Last); i++) { \
139 if (Filter(static_cast<Type>(i))) { \
140 CHECK_OFFSET(Class::Getter(static_cast<Type>(i)), Class##_##Getter[i]); \
141 } \
142 }
143#define CHECK_CONSTANT(Class, Name) CHECK_OFFSET(Class::Name, Class##_##Name);
144#endif // defined(DART_PRECOMPILED_RUNTIME)
145
146 COMMON_OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF, CHECK_RANGE,
147 CHECK_CONSTANT)
148
149 NOT_IN_PRECOMPILED_RUNTIME(JIT_OFFSETS_LIST(
150 CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF, CHECK_RANGE, CHECK_CONSTANT))
151
152 if (!ok) {
153 FATAL(
154 "CheckOffsets failed. Try updating offsets by running "
155 "./tools/run_offsets_extractor.sh");
156 }
157#undef CHECK_FIELD
158#undef CHECK_ARRAY
159#undef CHECK_ARRAY_STRUCTFIELD
160#undef CHECK_SIZEOF
161#undef CHECK_RANGE
162#undef CHECK_CONSTANT
163#undef CHECK_OFFSET
164#endif // !defined(IS_SIMARM_X64)
165}
166
167char* Dart::Init(const uint8_t* vm_isolate_snapshot,
168 const uint8_t* instructions_snapshot,
169 Dart_IsolateGroupCreateCallback create_group,
170 Dart_InitializeIsolateCallback initialize_isolate,
171 Dart_IsolateShutdownCallback shutdown,
172 Dart_IsolateCleanupCallback cleanup,
173 Dart_IsolateGroupCleanupCallback cleanup_group,
174 Dart_ThreadExitCallback thread_exit,
175 Dart_FileOpenCallback file_open,
176 Dart_FileReadCallback file_read,
177 Dart_FileWriteCallback file_write,
178 Dart_FileCloseCallback file_close,
179 Dart_EntropySource entropy_source,
180 Dart_GetVMServiceAssetsArchive get_service_assets,
181 bool start_kernel_isolate,
182 Dart_CodeObserver* observer) {
183 CheckOffsets();
184 // TODO(iposva): Fix race condition here.
185 if (vm_isolate_ != NULL || !Flags::Initialized()) {
186 return Utils::StrDup("VM already initialized or flags not initialized.");
187 }
188
189 if (FLAG_causal_async_stacks && FLAG_lazy_async_stacks) {
190 return Utils::StrDup(
191 "To use --lazy-async-stacks, please disable --causal-async-stacks!");
192 }
193
194 const Snapshot* snapshot = nullptr;
195 if (vm_isolate_snapshot != nullptr) {
196 snapshot = Snapshot::SetupFromBuffer(vm_isolate_snapshot);
197 if (snapshot == nullptr) {
198 return Utils::StrDup("Invalid vm isolate snapshot seen");
199 }
200 }
201
202 // We are initializing the VM. We will take the VM-global flags used
203 // during snapshot generation time also at runtime (this avoids the need
204 // for the embedder to pass the same flags used during snapshot generation
205 // also to the runtime).
206 if (snapshot != nullptr) {
207 char* error =
208 SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(snapshot);
209 if (error != nullptr) {
210 return error;
211 }
212 }
213
214 FrameLayout::Init();
215
216 set_thread_exit_callback(thread_exit);
217 SetFileCallbacks(file_open, file_read, file_write, file_close);
218 set_entropy_source_callback(entropy_source);
219 OS::Init();
220 NOT_IN_PRODUCT(CodeObservers::Init());
221 if (observer != nullptr) {
222 NOT_IN_PRODUCT(CodeObservers::RegisterExternal(*observer));
223 }
224 start_time_micros_ = OS::GetCurrentMonotonicMicros();
225 VirtualMemory::Init();
226 OSThread::Init();
227 Zone::Init();
228#if defined(SUPPORT_TIMELINE)
229 Timeline::Init();
230 TimelineBeginEndScope tbes(Timeline::GetVMStream(), "Dart::Init");
231#endif
232 IsolateGroup::Init();
233 Isolate::InitVM();
234 PortMap::Init();
235 FreeListElement::Init();
236 ForwardingCorpse::Init();
237 Api::Init();
238 NativeSymbolResolver::Init();
239 NOT_IN_PRODUCT(Profiler::Init());
240 SemiSpace::Init();
241 NOT_IN_PRODUCT(Metric::Init());
242 StoreBuffer::Init();
243 MarkingStack::Init();
244
245#if defined(USING_SIMULATOR)
246 Simulator::Init();
247#endif
248 // Create the read-only handles area.
249 ASSERT(predefined_handles_ == NULL);
250 predefined_handles_ = new ReadOnlyHandles();
251 // Create the VM isolate and finish the VM initialization.
252 ASSERT(thread_pool_ == NULL);
253 thread_pool_ = new ThreadPool();
254 {
255 ASSERT(vm_isolate_ == NULL);
256 ASSERT(Flags::Initialized());
257 const bool is_vm_isolate = true;
258
259 // Setup default flags for the VM isolate.
260 Dart_IsolateFlags api_flags;
261 Isolate::FlagsInitialize(&api_flags);
262
263 // We make a fake [IsolateGroupSource] here, since the "vm-isolate" is not
264 // really an isolate itself - it acts more as a container for VM-global
265 // objects.
266 std::unique_ptr<IsolateGroupSource> source(
267 new IsolateGroupSource(nullptr, kVmIsolateName, vm_isolate_snapshot,
268 instructions_snapshot, nullptr, -1, api_flags));
269 // ObjectStore should be created later, after null objects are initialized.
270 auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr,
271 /*object_store=*/nullptr);
272 group->CreateHeap(/*is_vm_isolate=*/true,
273 /*is_service_or_kernel_isolate=*/false);
274 IsolateGroup::RegisterIsolateGroup(group);
275 vm_isolate_ =
276 Isolate::InitIsolate(kVmIsolateName, group, api_flags, is_vm_isolate);
277 group->set_initial_spawn_successful();
278
279 // Verify assumptions about executing in the VM isolate.
280 ASSERT(vm_isolate_ == Isolate::Current());
281 ASSERT(vm_isolate_ == Thread::Current()->isolate());
282
283 Thread* T = Thread::Current();
284 ASSERT(T != NULL);
285 StackZone zone(T);
286 HandleScope handle_scope(T);
287 Object::InitNullAndBool(vm_isolate_);
288 vm_isolate_->set_object_store(new ObjectStore());
289 vm_isolate_->isolate_object_store()->Init();
290 vm_isolate_->isolate_group_->object_store_ =
291 vm_isolate_->object_store_shared_ptr_;
292 TargetCPUFeatures::Init();
293 Object::Init(vm_isolate_);
294 ArgumentsDescriptor::Init();
295 ICData::Init();
296 SubtypeTestCache::Init();
297 if (vm_isolate_snapshot != NULL) {
298#if defined(SUPPORT_TIMELINE)
299 TimelineBeginEndScope tbes(Timeline::GetVMStream(), "ReadVMSnapshot");
300#endif
301 ASSERT(snapshot != nullptr);
302 vm_snapshot_kind_ = snapshot->kind();
303
304 if (Snapshot::IncludesCode(vm_snapshot_kind_)) {
305 if (vm_snapshot_kind_ == Snapshot::kFullAOT) {
306#if !defined(DART_PRECOMPILED_RUNTIME)
307 return Utils::StrDup("JIT runtime cannot run a precompiled snapshot");
308#endif
309 }
310 if (instructions_snapshot == NULL) {
311 return Utils::StrDup("Missing instructions snapshot");
312 }
313 } else if (Snapshot::IsFull(vm_snapshot_kind_)) {
314#if defined(DART_PRECOMPILED_RUNTIME)
315 return Utils::StrDup(
316 "Precompiled runtime requires a precompiled snapshot");
317#else
318 StubCode::Init();
319 Object::FinishInit(vm_isolate_);
320 // MallocHooks can't be initialized until StubCode has been since stack
321 // trace generation relies on stub methods that are generated in
322 // StubCode::Init().
323 // TODO(bkonyi) Split initialization for stack trace collection from the
324 // initialization for the actual malloc hooks to increase accuracy of
325 // memory consumption statistics.
326 MallocHooks::Init();
327#endif
328 } else {
329 return Utils::StrDup("Invalid vm isolate snapshot seen");
330 }
331 FullSnapshotReader reader(snapshot, instructions_snapshot, T);
332 const Error& error = Error::Handle(reader.ReadVMSnapshot());
333 if (!error.IsNull()) {
334 // Must copy before leaving the zone.
335 return Utils::StrDup(error.ToErrorCString());
336 }
337
338 Object::FinishInit(vm_isolate_);
339#if defined(SUPPORT_TIMELINE)
340 if (tbes.enabled()) {
341 tbes.SetNumArguments(2);
342 tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
343 tbes.FormatArgument(
344 1, "heapSize", "%" Pd64,
345 vm_isolate_->heap()->UsedInWords(Heap::kOld) * kWordSize);
346 }
347#endif // !defined(PRODUCT)
348 if (FLAG_trace_isolates) {
349 OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
350 snapshot->length());
351 vm_isolate_->heap()->PrintSizes();
352 MegamorphicCacheTable::PrintSizes(vm_isolate_);
353 intptr_t size;
354 intptr_t capacity;
355 Symbols::GetStats(vm_isolate_, &size, &capacity);
356 OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
357 OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
358 }
359 } else {
360#if defined(DART_PRECOMPILED_RUNTIME)
361 return Utils::StrDup(
362 "Precompiled runtime requires a precompiled snapshot");
363#else
364 vm_snapshot_kind_ = Snapshot::kNone;
365 StubCode::Init();
366 Object::FinishInit(vm_isolate_);
367 // MallocHooks can't be initialized until StubCode has been since stack
368 // trace generation relies on stub methods that are generated in
369 // StubCode::Init().
370 // TODO(bkonyi) Split initialization for stack trace collection from the
371 // initialization for the actual malloc hooks to increase accuracy of
372 // memory consumption statistics.
373 MallocHooks::Init();
374 Symbols::Init(vm_isolate_);
375#endif
376 }
377 // We need to initialize the constants here for the vm isolate thread due to
378 // bootstrapping issues.
379 T->InitVMConstants();
380#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
381 // Dart VM requires at least SSE2.
382 if (!TargetCPUFeatures::sse2_supported()) {
383 return Utils::StrDup("SSE2 is required.");
384 }
385#endif
386 {
387#if defined(SUPPORT_TIMELINE)
388 TimelineBeginEndScope tbes(Timeline::GetVMStream(), "FinalizeVMIsolate");
389#endif
390 Object::FinalizeVMIsolate(vm_isolate_);
391 }
392#if defined(DEBUG)
393 vm_isolate_->heap()->Verify(kRequireMarked);
394#endif
395 }
396 // Allocate the "persistent" scoped handles for the predefined API
397 // values (such as Dart_True, Dart_False and Dart_Null).
398 Api::InitHandles();
399
400 Thread::ExitIsolate(); // Unregister the VM isolate from this thread.
401 Isolate::SetCreateGroupCallback(create_group);
402 Isolate::SetInitializeCallback_(initialize_isolate);
403 Isolate::SetShutdownCallback(shutdown);
404 Isolate::SetCleanupCallback(cleanup);
405 Isolate::SetGroupCleanupCallback(cleanup_group);
406
407#ifndef PRODUCT
408 const bool support_service = true;
409 Service::SetGetServiceAssetsCallback(get_service_assets);
410#else
411 const bool support_service = false;
412#endif
413
414 const bool is_dart2_aot_precompiler =
415 FLAG_precompiled_mode && !kDartPrecompiledRuntime;
416
417 if (!is_dart2_aot_precompiler &&
418 (support_service || !kDartPrecompiledRuntime)) {
419 ServiceIsolate::Run();
420 }
421
422#ifndef DART_PRECOMPILED_RUNTIME
423 if (start_kernel_isolate) {
424 KernelIsolate::InitializeState();
425 }
426#endif // DART_PRECOMPILED_RUNTIME
427
428 return NULL;
429}
430
431static void DumpAliveIsolates(intptr_t num_attempts,
432 bool only_aplication_isolates) {
433 IsolateGroup::ForEach([&](IsolateGroup* group) {
434 group->ForEachIsolate([&](Isolate* isolate) {
435 if (!only_aplication_isolates || !Isolate::IsVMInternalIsolate(isolate)) {
436 OS::PrintErr("Attempt:%" Pd " waiting for isolate %s to check in\n",
437 num_attempts, isolate->name());
438 }
439 });
440 });
441}
442
443static bool OnlyVmIsolateLeft() {
444 intptr_t count = 0;
445 bool found_vm_isolate = false;
446 IsolateGroup::ForEach([&](IsolateGroup* group) {
447 group->ForEachIsolate([&](Isolate* isolate) {
448 count++;
449 if (isolate == Dart::vm_isolate()) {
450 found_vm_isolate = true;
451 }
452 });
453 });
454 return count == 1 && found_vm_isolate;
455}
456
457// This waits until only the VM, service and kernel isolates are in the list.
458void Dart::WaitForApplicationIsolateShutdown() {
459 ASSERT(!Isolate::creation_enabled_);
460 MonitorLocker ml(Isolate::isolate_creation_monitor_);
461 intptr_t num_attempts = 0;
462 while (IsolateGroup::HasApplicationIsolateGroups()) {
463 Monitor::WaitResult retval = ml.Wait(1000);
464 if (retval == Monitor::kTimedOut) {
465 num_attempts += 1;
466 if (num_attempts > 10) {
467 DumpAliveIsolates(num_attempts, /*only_application_isolates=*/true);
468 }
469 }
470 }
471}
472
473// This waits until only the VM isolate remains in the list.
474void Dart::WaitForIsolateShutdown() {
475 ASSERT(!Isolate::creation_enabled_);
476 MonitorLocker ml(Isolate::isolate_creation_monitor_);
477 intptr_t num_attempts = 0;
478 while (!IsolateGroup::HasOnlyVMIsolateGroup()) {
479 Monitor::WaitResult retval = ml.Wait(1000);
480 if (retval == Monitor::kTimedOut) {
481 num_attempts += 1;
482 if (num_attempts > 10) {
483 DumpAliveIsolates(num_attempts, /*only_application_isolates=*/false);
484 }
485 }
486 }
487
488 ASSERT(OnlyVmIsolateLeft());
489}
490
491char* Dart::Cleanup() {
492 ASSERT(Isolate::Current() == NULL);
493 if (vm_isolate_ == NULL) {
494 return Utils::StrDup("VM already terminated.");
495 }
496
497 if (FLAG_trace_shutdown) {
498 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Starting shutdown\n",
499 UptimeMillis());
500 }
501
502#if !defined(PRODUCT)
503 if (FLAG_trace_shutdown) {
504 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down profiling\n",
505 UptimeMillis());
506 }
507 Profiler::Cleanup();
508#endif // !defined(PRODUCT)
509
510 NativeSymbolResolver::Cleanup();
511
512 // Disable the creation of new isolates.
513 if (FLAG_trace_shutdown) {
514 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling isolate creation\n",
515 UptimeMillis());
516 }
517 Isolate::DisableIsolateCreation();
518
519 // Send the OOB Kill message to all remaining application isolates.
520 if (FLAG_trace_shutdown) {
521 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Killing all app isolates\n",
522 UptimeMillis());
523 }
524 Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
525
526 // Wait for all isolates, but the service and the vm isolate to shut down.
527 // Only do that if there is a service isolate running.
528 if (ServiceIsolate::IsRunning() || KernelIsolate::IsRunning()) {
529 if (FLAG_trace_shutdown) {
530 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down app isolates\n",
531 UptimeMillis());
532 }
533 WaitForApplicationIsolateShutdown();
534 }
535
536 // Shutdown the kernel isolate.
537 if (FLAG_trace_shutdown) {
538 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down kernel isolate\n",
539 UptimeMillis());
540 }
541 KernelIsolate::Shutdown();
542
543 // Shutdown the service isolate.
544 if (FLAG_trace_shutdown) {
545 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
546 UptimeMillis());
547 }
548 ServiceIsolate::Shutdown();
549
550 // Wait for the remaining isolate (service isolate) to shutdown
551 // before shutting down the thread pool.
552 if (FLAG_trace_shutdown) {
553 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
554 UptimeMillis());
555 }
556 WaitForIsolateShutdown();
557
558#if !defined(PRODUCT)
559 {
560 // IMPORTANT: the code below enters VM isolate so that Metric::Cleanup could
561 // create a StackZone. We *must* wait for all other isolate to shutdown
562 // before entering VM isolate because code in the isolate initialization
563 // calls VerifyBootstrapClasses, which calls Heap::Verify which calls
564 // Scavenger::VisitObjects on the VM isolate's new space without taking
565 // any sort of locks: assuming that vm isolate is immutable and never
566 // entered by a mutator thread - which is in general true, but is violated
567 // by the code below.
568 if (FLAG_trace_shutdown) {
569 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Entering vm isolate\n",
570 UptimeMillis());
571 }
572 bool result = Thread::EnterIsolate(vm_isolate_);
573 ASSERT(result);
574 Metric::Cleanup();
575 Thread::ExitIsolate();
576 }
577#endif
578
579 // Shutdown the thread pool. On return, all thread pool threads have exited.
580 if (FLAG_trace_shutdown) {
581 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
582 UptimeMillis());
583 }
584 thread_pool_->Shutdown();
585 delete thread_pool_;
586 thread_pool_ = NULL;
587
588 Api::Cleanup();
589 delete predefined_handles_;
590 predefined_handles_ = NULL;
591
592 // Set the VM isolate as current isolate.
593 if (FLAG_trace_shutdown) {
594 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
595 UptimeMillis());
596 }
597
598 // If Dart_Cleanup() is called on a thread which hasn't invoked any Dart API
599 // functions before, entering the "vm-isolate" will cause lazy creation of a
600 // OSThread (which is attached to the current thread via TLS).
601 //
602 // If we run in PRODUCT mode this lazy creation of OSThread can happen here,
603 // which is why disabling the OSThread creation has to come after entering the
604 // "vm-isolate".
605 const bool result = Thread::EnterIsolate(vm_isolate_);
606 ASSERT(result);
607
608 // Disable creation of any new OSThread structures which means no more new
609 // threads can do an EnterIsolate. This must come after isolate shutdown
610 // because new threads may need to be spawned to shutdown the isolates.
611 // This must come after deletion of the thread pool to avoid a race in which
612 // a thread spawned by the thread pool does not exit through the thread
613 // pool, messing up its bookkeeping.
614 if (FLAG_trace_shutdown) {
615 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
616 UptimeMillis());
617 }
618 OSThread::DisableOSThreadCreation();
619
620 ShutdownIsolate();
621 vm_isolate_ = NULL;
622 ASSERT(Isolate::IsolateListLength() == 0);
623 PortMap::Cleanup();
624 IsolateGroup::Cleanup();
625 ICData::Cleanup();
626 SubtypeTestCache::Cleanup();
627 ArgumentsDescriptor::Cleanup();
628 TargetCPUFeatures::Cleanup();
629 MarkingStack::Cleanup();
630 StoreBuffer::Cleanup();
631 Object::Cleanup();
632 SemiSpace::Cleanup();
633 StubCode::Cleanup();
634#if defined(SUPPORT_TIMELINE)
635 if (FLAG_trace_shutdown) {
636 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
637 UptimeMillis());
638 }
639 Timeline::Cleanup();
640#endif
641 Zone::Cleanup();
642 // Delete the current thread's TLS and set it's TLS to null.
643 // If it is the last thread then the destructor would call
644 // OSThread::Cleanup.
645 OSThread* os_thread = OSThread::Current();
646 OSThread::SetCurrent(NULL);
647 delete os_thread;
648 if (FLAG_trace_shutdown) {
649 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleted os_thread\n",
650 UptimeMillis());
651 }
652
653 if (FLAG_trace_shutdown) {
654 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting code observers\n",
655 UptimeMillis());
656 }
657 NOT_IN_PRODUCT(CodeObservers::Cleanup());
658 OS::Cleanup();
659 if (FLAG_trace_shutdown) {
660 OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Done\n", UptimeMillis());
661 }
662 MallocHooks::Cleanup();
663 Flags::Cleanup();
664#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
665 IsolateGroupReloadContext::SetFileModifiedCallback(NULL);
666 Service::SetEmbedderStreamCallbacks(NULL, NULL);
667#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
668 return NULL;
669}
670
671Isolate* Dart::CreateIsolate(const char* name_prefix,
672 const Dart_IsolateFlags& api_flags,
673 IsolateGroup* isolate_group) {
674 // Create a new isolate.
675 Isolate* isolate =
676 Isolate::InitIsolate(name_prefix, isolate_group, api_flags);
677 return isolate;
678}
679
680#if defined(DART_PRECOMPILED_RUNTIME)
681static bool CloneIntoChildIsolateAOT(Thread* T,
682 Isolate* I,
683 IsolateGroup* source_isolate_group) {
684 // In AOT we speed up isolate spawning by copying donor's isolate structure.
685 if (source_isolate_group == nullptr) {
686 return false;
687 }
688 I->isolate_object_store()->Init();
689 I->isolate_object_store()->PreallocateObjects();
690 I->set_field_table(
691 T, source_isolate_group->saved_initial_field_table()->Clone());
692
693 return true;
694}
695#endif
696
697ErrorPtr Dart::InitIsolateFromSnapshot(Thread* T,
698 Isolate* I,
699 const uint8_t* snapshot_data,
700 const uint8_t* snapshot_instructions,
701 const uint8_t* kernel_buffer,
702 intptr_t kernel_buffer_size) {
703 Error& error = Error::Handle(T->zone());
704 error = Object::Init(I, kernel_buffer, kernel_buffer_size);
705 if (!error.IsNull()) {
706 return error.raw();
707 }
708 if ((snapshot_data != NULL) && kernel_buffer == NULL) {
709 // Read the snapshot and setup the initial state.
710#if defined(SUPPORT_TIMELINE)
711 TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
712 "ReadProgramSnapshot");
713#endif // defined(SUPPORT_TIMELINE)
714 // TODO(turnidge): Remove once length is not part of the snapshot.
715 const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
716 if (snapshot == NULL) {
717 const String& message = String::Handle(String::New("Invalid snapshot"));
718 return ApiError::New(message);
719 }
720 if (!IsSnapshotCompatible(vm_snapshot_kind_, snapshot->kind())) {
721 const String& message = String::Handle(String::NewFormatted(
722 "Incompatible snapshot kinds: vm '%s', isolate '%s'",
723 Snapshot::KindToCString(vm_snapshot_kind_),
724 Snapshot::KindToCString(snapshot->kind())));
725 return ApiError::New(message);
726 }
727 if (FLAG_trace_isolates) {
728 OS::PrintErr("Size of isolate snapshot = %" Pd "\n", snapshot->length());
729 }
730 FullSnapshotReader reader(snapshot, snapshot_instructions, T);
731 const Error& error = Error::Handle(reader.ReadProgramSnapshot());
732 if (!error.IsNull()) {
733 return error.raw();
734 }
735
736 I->group()->set_saved_initial_field_table(
737 std::shared_ptr<FieldTable>(I->field_table()->Clone()));
738
739#if defined(SUPPORT_TIMELINE)
740 if (tbes.enabled()) {
741 tbes.SetNumArguments(2);
742 tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
743 tbes.FormatArgument(1, "heapSize", "%" Pd64,
744 I->heap()->UsedInWords(Heap::kOld) * kWordSize);
745 }
746#endif // defined(SUPPORT_TIMELINE)
747 if (FLAG_trace_isolates) {
748 I->heap()->PrintSizes();
749 MegamorphicCacheTable::PrintSizes(I);
750 }
751 } else {
752 if ((vm_snapshot_kind_ != Snapshot::kNone) && kernel_buffer == NULL) {
753 const String& message =
754 String::Handle(String::New("Missing isolate snapshot"));
755 return ApiError::New(message);
756 }
757 }
758
759 return Error::null();
760}
761
762bool Dart::DetectNullSafety(const char* script_uri,
763 const uint8_t* snapshot_data,
764 const uint8_t* snapshot_instructions,
765 const uint8_t* kernel_buffer,
766 intptr_t kernel_buffer_size,
767 const char* package_config,
768 const char* original_working_directory) {
769#if !defined(DART_PRECOMPILED_RUNTIME)
770 // Before creating the isolate we first determine the null safety mode
771 // in which the isolate needs to run based on one of these factors :
772 // - if loading from source, based on opt-in status of the source
773 // - if loading from a kernel file, based on the mode used when
774 // generating the kernel file
775 // - if loading from an appJIT, based on the mode used
776 // when generating the snapshot.
777 ASSERT(FLAG_sound_null_safety == kNullSafetyOptionUnspecified);
778
779 // If snapshot is an appJIT/AOT snapshot we will figure out the mode by
780 // sniffing the feature string in the snapshot.
781 if (snapshot_data != nullptr) {
782 // Read the snapshot and check for null safety option.
783 const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
784 if (Snapshot::IncludesCode(snapshot->kind())) {
785 return SnapshotHeaderReader::NullSafetyFromSnapshot(snapshot);
786 }
787 }
788
789 // If kernel_buffer is specified, it could be a self contained
790 // kernel file or the kernel file of the application,
791 // figure out the null safety mode by sniffing the kernel file.
792 if (kernel_buffer != nullptr) {
793 const char* error = nullptr;
794 std::unique_ptr<kernel::Program> program = kernel::Program::ReadFromBuffer(
795 kernel_buffer, kernel_buffer_size, &error);
796 if (program != nullptr) {
797 return program->compilation_mode() == NNBDCompiledMode::kStrong;
798 }
799 return false;
800 }
801
802 // If we are loading from source, figure out the mode from the source.
803 if (KernelIsolate::GetExperimentalFlag("non-nullable")) {
804 return KernelIsolate::DetectNullSafety(script_uri, package_config,
805 original_working_directory);
806 }
807 return false;
808#else
809 UNREACHABLE();
810#endif // !defined(DART_PRECOMPILED_RUNTIME)
811}
812
813#if defined(DART_PRECOMPILED_RUNTIME)
814static void PrintLLVMConstantPool(Thread* T, Isolate* I) {
815 StackZone printing_zone(T);
816 HandleScope printing_scope(T);
817 TextBuffer b(1000);
818 const auto& constants =
819 GrowableObjectArray::Handle(I->object_store()->llvm_constant_pool());
820 if (constants.IsNull()) {
821 b.AddString("No constant pool information in snapshot.\n\n");
822 } else {
823 auto const len = constants.Length();
824 b.Printf("Constant pool contents (length %" Pd "):\n", len);
825 auto& obj = Object::Handle();
826 for (intptr_t i = 0; i < len; i++) {
827 obj = constants.At(i);
828 b.Printf(" %5" Pd ": ", i);
829 if (obj.IsString()) {
830 b.AddChar('"');
831 b.AddEscapedString(obj.ToCString());
832 b.AddChar('"');
833 } else {
834 b.AddString(obj.ToCString());
835 }
836 b.AddChar('\n');
837 }
838 b.AddString("End of constant pool.\n\n");
839 }
840 const auto& functions =
841 GrowableObjectArray::Handle(I->object_store()->llvm_function_pool());
842 if (functions.IsNull()) {
843 b.AddString("No function pool information in snapshot.\n\n");
844 } else {
845 auto const len = functions.Length();
846 b.Printf("Function pool contents (length %" Pd "):\n", len);
847 auto& obj = Function::Handle();
848 for (intptr_t i = 0; i < len; i++) {
849 obj ^= functions.At(i);
850 ASSERT(!obj.IsNull());
851 b.Printf(" %5" Pd ": %s\n", i, obj.ToFullyQualifiedCString());
852 }
853 b.AddString("End of function pool.\n\n");
854 }
855 THR_Print("%s", b.buffer());
856}
857#endif
858
859ErrorPtr Dart::InitializeIsolate(const uint8_t* snapshot_data,
860 const uint8_t* snapshot_instructions,
861 const uint8_t* kernel_buffer,
862 intptr_t kernel_buffer_size,
863 IsolateGroup* source_isolate_group,
864 void* isolate_data) {
865 // Initialize the new isolate.
866 Thread* T = Thread::Current();
867 Isolate* I = T->isolate();
868#if defined(SUPPORT_TIMELINE)
869 TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
870 "InitializeIsolate");
871 tbes.SetNumArguments(1);
872 tbes.CopyArgument(0, "isolateName", I->name());
873#endif
874 ASSERT(I != NULL);
875 StackZone zone(T);
876 HandleScope handle_scope(T);
877 bool was_child_cloned_into_existing_isolate = false;
878#if defined(DART_PRECOMPILED_RUNTIME)
879 if (CloneIntoChildIsolateAOT(T, I, source_isolate_group)) {
880 was_child_cloned_into_existing_isolate = true;
881 } else {
882#endif
883 const Error& error = Error::Handle(
884 InitIsolateFromSnapshot(T, I, snapshot_data, snapshot_instructions,
885 kernel_buffer, kernel_buffer_size));
886 if (!error.IsNull()) {
887 return error.raw();
888 }
889#if defined(DART_PRECOMPILED_RUNTIME)
890 }
891#endif
892
893 Object::VerifyBuiltinVtables();
894 DEBUG_ONLY(I->heap()->Verify(kForbidMarked));
895
896#if defined(DART_PRECOMPILED_RUNTIME)
897 ASSERT(I->object_store()->build_method_extractor_code() != Code::null());
898 if (FLAG_print_llvm_constant_pool) {
899 PrintLLVMConstantPool(T, I);
900 }
901#else
902#if !defined(TARGET_ARCH_IA32)
903 if (I != Dart::vm_isolate()) {
904 I->object_store()->set_build_method_extractor_code(
905 Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr)));
906 }
907#endif
908#endif // defined(DART_PRECOMPILED_RUNTIME)
909
910 I->set_ic_miss_code(StubCode::SwitchableCallMiss());
911
912 if ((snapshot_data == NULL) || (kernel_buffer != NULL)) {
913 Error& error = Error::Handle();
914 error ^= I->object_store()->PreallocateObjects();
915 if (!error.IsNull()) {
916 return error.raw();
917 }
918 error ^= I->isolate_object_store()->PreallocateObjects();
919 if (!error.IsNull()) {
920 return error.raw();
921 }
922 }
923
924 if (!was_child_cloned_into_existing_isolate) {
925 I->heap()->InitGrowthControl();
926 }
927 I->set_init_callback_data(isolate_data);
928 if (FLAG_print_class_table) {
929 I->class_table()->Print();
930 }
931#if !defined(PRODUCT)
932 ServiceIsolate::MaybeMakeServiceIsolate(I);
933 if (!ServiceIsolate::IsServiceIsolate(I) &&
934 !KernelIsolate::IsKernelIsolate(I)) {
935 I->message_handler()->set_should_pause_on_start(
936 FLAG_pause_isolates_on_start);
937 I->message_handler()->set_should_pause_on_exit(FLAG_pause_isolates_on_exit);
938 }
939#endif // !defined(PRODUCT)
940
941 ServiceIsolate::SendIsolateStartupMessage();
942#if !defined(PRODUCT)
943 I->debugger()->NotifyIsolateCreated();
944#endif
945
946 // Create tag table.
947 I->set_tag_table(GrowableObjectArray::Handle(GrowableObjectArray::New()));
948 // Set up default UserTag.
949 const UserTag& default_tag = UserTag::Handle(UserTag::DefaultTag());
950 I->set_current_tag(default_tag);
951
952 if (FLAG_keep_code) {
953 I->set_deoptimized_code_array(
954 GrowableObjectArray::Handle(GrowableObjectArray::New()));
955 }
956 return Error::null();
957}
958
959const char* Dart::FeaturesString(Isolate* isolate,
960 bool is_vm_isolate,
961 Snapshot::Kind kind) {
962 TextBuffer buffer(64);
963
964// Different fields are included for DEBUG/RELEASE/PRODUCT.
965#if defined(DEBUG)
966 buffer.AddString("debug");
967#elif defined(PRODUCT)
968 buffer.AddString("product");
969#else
970 buffer.AddString("release");
971#endif
972
973#define ADD_FLAG(name, value) \
974 do { \
975 buffer.AddString(value ? (" " #name) : (" no-" #name)); \
976 } while (0);
977#define ADD_P(name, T, DV, C) ADD_FLAG(name, FLAG_##name)
978#define ADD_R(name, PV, T, DV, C) ADD_FLAG(name, FLAG_##name)
979#define ADD_C(name, PCV, PV, T, DV, C) ADD_FLAG(name, FLAG_##name)
980#define ADD_D(name, T, DV, C) ADD_FLAG(name, FLAG_##name)
981
982#define ADD_ISOLATE_FLAG(name, isolate_flag, flag) \
983 do { \
984 const bool value = (isolate != NULL) ? isolate->name() : flag; \
985 ADD_FLAG(#name, value); \
986 } while (0);
987
988 if (Snapshot::IncludesCode(kind)) {
989 VM_GLOBAL_FLAG_LIST(ADD_P, ADD_R, ADD_C, ADD_D);
990
991 // enabling assertions affects deopt ids.
992 ADD_ISOLATE_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
993 if (kind == Snapshot::kFullJIT) {
994 ADD_ISOLATE_FLAG(use_field_guards, use_field_guards,
995 FLAG_use_field_guards);
996 ADD_ISOLATE_FLAG(use_osr, use_osr, FLAG_use_osr);
997 }
998#if !defined(PRODUCT)
999 buffer.AddString(FLAG_code_comments ? " code-comments"
1000 : " no-code-comments");
1001#endif
1002
1003// Generated code must match the host architecture and ABI.
1004#if defined(TARGET_ARCH_ARM)
1005#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
1006 buffer.AddString(" arm-ios");
1007#else
1008 buffer.AddString(" arm-eabi");
1009#endif
1010 buffer.AddString(TargetCPUFeatures::hardfp_supported() ? " hardfp"
1011 : " softfp");
1012#elif defined(TARGET_ARCH_ARM64)
1013#if defined(TARGET_OS_FUCHSIA)
1014 // See signal handler cheat in Assembler::EnterFrame.
1015 buffer.AddString(" arm64-fuchsia");
1016#else
1017 buffer.AddString(" arm64-sysv");
1018#endif
1019#elif defined(TARGET_ARCH_IA32)
1020 buffer.AddString(" ia32");
1021#elif defined(TARGET_ARCH_X64)
1022#if defined(TARGET_OS_WINDOWS)
1023 buffer.AddString(" x64-win");
1024#else
1025 buffer.AddString(" x64-sysv");
1026#endif
1027
1028#else
1029#error What architecture?
1030#endif
1031
1032 if (isolate != NULL) {
1033 if (isolate->null_safety()) {
1034 buffer.AddString(" null-safety");
1035 } else {
1036 buffer.AddString(" no-null-safety");
1037 }
1038 } else {
1039 if (FLAG_sound_null_safety == kNullSafetyOptionStrong) {
1040 buffer.AddString(" null-safety");
1041 } else {
1042 buffer.AddString(" no-null-safety");
1043 }
1044 }
1045 }
1046
1047#undef ADD_ISOLATE_FLAG
1048#undef ADD_D
1049#undef ADD_C
1050#undef ADD_R
1051#undef ADD_P
1052#undef ADD_FLAG
1053
1054 return buffer.Steal();
1055}
1056
1057void Dart::RunShutdownCallback() {
1058 Thread* thread = Thread::Current();
1059 ASSERT(thread->execution_state() == Thread::kThreadInVM);
1060 Isolate* isolate = thread->isolate();
1061 void* isolate_group_data = isolate->group()->embedder_data();
1062 void* isolate_data = isolate->init_callback_data();
1063 Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
1064 if (callback != NULL) {
1065 TransitionVMToNative transition(thread);
1066 (callback)(isolate_group_data, isolate_data);
1067 }
1068}
1069
1070void Dart::ShutdownIsolate(Isolate* isolate) {
1071 ASSERT(Isolate::Current() == NULL);
1072 // We need to enter the isolate in order to shut it down.
1073 bool result = Thread::EnterIsolate(isolate);
1074 ASSERT(result);
1075 ShutdownIsolate();
1076 // Since the isolate is shutdown and deleted, there is no need to
1077 // exit the isolate here.
1078 ASSERT(Isolate::Current() == NULL);
1079}
1080
1081void Dart::ShutdownIsolate() {
1082 Isolate::Current()->Shutdown();
1083}
1084
1085bool Dart::VmIsolateNameEquals(const char* name) {
1086 ASSERT(name != NULL);
1087 return (strcmp(name, kVmIsolateName) == 0);
1088}
1089
1090int64_t Dart::UptimeMicros() {
1091 return OS::GetCurrentMonotonicMicros() - Dart::start_time_micros_;
1092}
1093
1094uword Dart::AllocateReadOnlyHandle() {
1095 ASSERT(Isolate::Current() == Dart::vm_isolate());
1096 ASSERT(predefined_handles_ != NULL);
1097 return predefined_handles_->handles_.AllocateScopedHandle();
1098}
1099
1100LocalHandle* Dart::AllocateReadOnlyApiHandle() {
1101 ASSERT(Isolate::Current() == Dart::vm_isolate());
1102 ASSERT(predefined_handles_ != NULL);
1103 return predefined_handles_->api_handles_.AllocateHandle();
1104}
1105
1106bool Dart::IsReadOnlyHandle(uword address) {
1107 ASSERT(predefined_handles_ != NULL);
1108 return predefined_handles_->handles_.IsValidScopedHandle(address);
1109}
1110
1111bool Dart::IsReadOnlyApiHandle(Dart_Handle handle) {
1112 ASSERT(predefined_handles_ != NULL);
1113 return predefined_handles_->api_handles_.IsValidHandle(handle);
1114}
1115
1116} // namespace dart
1117