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 <utility>
6
7#include "vm/isolate.h"
8
9#include "include/dart_api.h"
10#include "include/dart_native_api.h"
11#include "platform/assert.h"
12#include "platform/atomic.h"
13#include "platform/text_buffer.h"
14#include "vm/class_finalizer.h"
15#include "vm/code_observers.h"
16#include "vm/compiler/jit/compiler.h"
17#include "vm/dart_api_message.h"
18#include "vm/dart_api_state.h"
19#include "vm/dart_entry.h"
20#include "vm/debugger.h"
21#include "vm/deopt_instructions.h"
22#include "vm/dispatch_table.h"
23#include "vm/flags.h"
24#include "vm/heap/heap.h"
25#include "vm/heap/pointer_block.h"
26#include "vm/heap/safepoint.h"
27#include "vm/heap/verifier.h"
28#include "vm/image_snapshot.h"
29#include "vm/interpreter.h"
30#include "vm/isolate_reload.h"
31#include "vm/kernel_isolate.h"
32#include "vm/lockers.h"
33#include "vm/log.h"
34#include "vm/message_handler.h"
35#include "vm/object.h"
36#include "vm/object_id_ring.h"
37#include "vm/object_store.h"
38#include "vm/os_thread.h"
39#include "vm/port.h"
40#include "vm/profiler.h"
41#include "vm/reusable_handles.h"
42#include "vm/reverse_pc_lookup_cache.h"
43#include "vm/service.h"
44#include "vm/service_event.h"
45#include "vm/service_isolate.h"
46#include "vm/simulator.h"
47#include "vm/stack_frame.h"
48#include "vm/stub_code.h"
49#include "vm/symbols.h"
50#include "vm/tags.h"
51#include "vm/thread_interrupter.h"
52#include "vm/thread_registry.h"
53#include "vm/timeline.h"
54#include "vm/timeline_analysis.h"
55#include "vm/visitor.h"
56
57#if !defined(DART_PRECOMPILED_RUNTIME)
58#include "vm/compiler/assembler/assembler.h"
59#include "vm/compiler/stub_code_compiler.h"
60#endif
61
62namespace dart {
63
64DECLARE_FLAG(bool, print_metrics);
65DECLARE_FLAG(bool, timing);
66DECLARE_FLAG(bool, trace_service);
67DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
68
69// Reload flags.
70DECLARE_FLAG(int, reload_every);
71#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
72DECLARE_FLAG(bool, check_reloaded);
73DECLARE_FLAG(bool, reload_every_back_off);
74DECLARE_FLAG(bool, trace_reload);
75#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
76
77static void DeterministicModeHandler(bool value) {
78 if (value) {
79 FLAG_background_compilation = false; // Timing dependent.
80 FLAG_concurrent_mark = false; // Timing dependent.
81 FLAG_concurrent_sweep = false; // Timing dependent.
82 FLAG_scavenger_tasks = 0; // Timing dependent.
83 FLAG_random_seed = 0x44617274; // "Dart"
84 }
85}
86
87DEFINE_FLAG_HANDLER(DeterministicModeHandler,
88 deterministic,
89 "Enable deterministic mode.");
90
91int FLAG_sound_null_safety = kNullSafetyOptionUnspecified;
92static void SoundNullSafetyHandler(bool value) {
93 FLAG_sound_null_safety =
94 value ? kNullSafetyOptionStrong : kNullSafetyOptionWeak;
95}
96
97DEFINE_FLAG_HANDLER(SoundNullSafetyHandler,
98 sound_null_safety,
99 "Respect the nullability of types at runtime.");
100
101DEFINE_FLAG(bool,
102 disable_thread_pool_limit,
103 false,
104 "Disables the limit of the thread pool (simulates custom embedder "
105 "with custom message handler on unlimited number of threads).");
106
107// Quick access to the locally defined thread() and isolate() methods.
108#define T (thread())
109#define I (isolate())
110
111#if defined(DEBUG)
112// Helper class to ensure that a live origin_id is never reused
113// and assigned to an isolate.
114class VerifyOriginId : public IsolateVisitor {
115 public:
116 explicit VerifyOriginId(Dart_Port id) : id_(id) {}
117
118 void VisitIsolate(Isolate* isolate) { ASSERT(isolate->origin_id() != id_); }
119
120 private:
121 Dart_Port id_;
122 DISALLOW_COPY_AND_ASSIGN(VerifyOriginId);
123};
124#endif
125
126static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
127 const Instance& obj) {
128 if (ApiObjectConverter::CanConvert(obj.raw())) {
129 return Message::New(dest_port, obj.raw(), Message::kNormalPriority);
130 } else {
131 MessageWriter writer(false);
132 return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
133 }
134}
135
136static InstancePtr DeserializeMessage(Thread* thread, Message* message) {
137 if (message == NULL) {
138 return Instance::null();
139 }
140 Zone* zone = thread->zone();
141 if (message->IsRaw()) {
142 return Instance::RawCast(message->raw_obj());
143 } else {
144 MessageSnapshotReader reader(message, thread);
145 const Object& obj = Object::Handle(zone, reader.ReadObject());
146 ASSERT(!obj.IsError());
147 return Instance::RawCast(obj.raw());
148 }
149}
150
151void IsolateGroupSource::add_loaded_blob(
152 Zone* zone,
153 const ExternalTypedData& external_typed_data) {
154 Array& loaded_blobs = Array::Handle();
155 bool saved_external_typed_data = false;
156 if (loaded_blobs_ != nullptr) {
157 loaded_blobs = loaded_blobs_;
158
159 // Walk the array, and (if stuff was removed) compact and reuse the space.
160 // Note that the space has to be compacted as the ordering is important.
161 WeakProperty& weak_property = WeakProperty::Handle();
162 WeakProperty& weak_property_tmp = WeakProperty::Handle();
163 ExternalTypedData& existing_entry = ExternalTypedData::Handle(zone);
164 intptr_t next_entry_index = 0;
165 for (intptr_t i = 0; i < loaded_blobs.Length(); i++) {
166 weak_property ^= loaded_blobs.At(i);
167 if (weak_property.key() != ExternalTypedData::null()) {
168 if (i != next_entry_index) {
169 existing_entry = ExternalTypedData::RawCast(weak_property.key());
170 weak_property_tmp ^= loaded_blobs.At(next_entry_index);
171 weak_property_tmp.set_key(existing_entry);
172 }
173 next_entry_index++;
174 }
175 }
176 if (next_entry_index < loaded_blobs.Length()) {
177 // There's now space to re-use.
178 weak_property ^= loaded_blobs.At(next_entry_index);
179 weak_property.set_key(external_typed_data);
180 next_entry_index++;
181 saved_external_typed_data = true;
182 }
183 if (next_entry_index < loaded_blobs.Length()) {
184 ExternalTypedData& nullExternalTypedData =
185 ExternalTypedData::Handle(zone);
186 while (next_entry_index < loaded_blobs.Length()) {
187 // Null out any extra spaces.
188 weak_property ^= loaded_blobs.At(next_entry_index);
189 weak_property.set_key(nullExternalTypedData);
190 next_entry_index++;
191 }
192 }
193 }
194 if (!saved_external_typed_data) {
195 const WeakProperty& weak_property =
196 WeakProperty::Handle(WeakProperty::New(Heap::kOld));
197 weak_property.set_key(external_typed_data);
198
199 intptr_t length = loaded_blobs.IsNull() ? 0 : loaded_blobs.Length();
200 Array& new_array =
201 Array::Handle(Array::Grow(loaded_blobs, length + 1, Heap::kOld));
202 new_array.SetAt(length, weak_property);
203 loaded_blobs_ = new_array.raw();
204 }
205 num_blob_loads_++;
206}
207
208void IdleTimeHandler::InitializeWithHeap(Heap* heap) {
209 MutexLocker ml(&mutex_);
210 ASSERT(heap_ == nullptr && heap != nullptr);
211 heap_ = heap;
212}
213
214bool IdleTimeHandler::ShouldCheckForIdle() {
215 MutexLocker ml(&mutex_);
216 return idle_start_time_ > 0 && FLAG_idle_timeout_micros != 0 &&
217 disabled_counter_ == 0;
218}
219
220void IdleTimeHandler::UpdateStartIdleTime() {
221 MutexLocker ml(&mutex_);
222 if (disabled_counter_ == 0) {
223 idle_start_time_ = OS::GetCurrentMonotonicMicros();
224 }
225}
226
227bool IdleTimeHandler::ShouldNotifyIdle(int64_t* expiry) {
228 const int64_t now = OS::GetCurrentMonotonicMicros();
229
230 MutexLocker ml(&mutex_);
231 if (idle_start_time_ > 0 && disabled_counter_ == 0) {
232 const int64_t expiry_time = idle_start_time_ + FLAG_idle_timeout_micros;
233 if (expiry_time < now) {
234 idle_start_time_ = 0;
235 return true;
236 }
237 }
238
239 *expiry = now + FLAG_idle_timeout_micros;
240 return false;
241}
242
243void IdleTimeHandler::NotifyIdle(int64_t deadline) {
244 {
245 MutexLocker ml(&mutex_);
246 disabled_counter_++;
247 }
248 if (heap_ != nullptr) {
249 heap_->NotifyIdle(deadline);
250 }
251 {
252 MutexLocker ml(&mutex_);
253 disabled_counter_--;
254 idle_start_time_ = 0;
255 }
256}
257
258void IdleTimeHandler::NotifyIdleUsingDefaultDeadline() {
259 const int64_t now = OS::GetCurrentMonotonicMicros();
260 NotifyIdle(now + FLAG_idle_timeout_micros);
261}
262
263DisableIdleTimerScope::DisableIdleTimerScope(IdleTimeHandler* handler)
264 : handler_(handler) {
265 if (handler_ != nullptr) {
266 MutexLocker ml(&handler_->mutex_);
267 ++handler_->disabled_counter_;
268 handler_->idle_start_time_ = 0;
269 }
270}
271
272DisableIdleTimerScope::~DisableIdleTimerScope() {
273 if (handler_ != nullptr) {
274 MutexLocker ml(&handler_->mutex_);
275 --handler_->disabled_counter_;
276 ASSERT(handler_->disabled_counter_ >= 0);
277 }
278}
279
280class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor {
281 public:
282 explicit FinalizeWeakPersistentHandlesVisitor(IsolateGroup* isolate_group)
283 : HandleVisitor(Thread::Current()), isolate_group_(isolate_group) {}
284
285 void VisitHandle(uword addr) {
286 auto handle = reinterpret_cast<FinalizablePersistentHandle*>(addr);
287 handle->UpdateUnreachable(isolate_group_);
288 }
289
290 private:
291 IsolateGroup* isolate_group_;
292
293 DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor);
294};
295
296void MutatorThreadPool::OnEnterIdleLocked(MonitorLocker* ml) {
297 if (FLAG_idle_timeout_micros == 0) return;
298
299 // If the isolate has not started running application code yet, we ignore the
300 // idle time.
301 if (!isolate_group_->initial_spawn_successful()) return;
302
303 int64_t idle_expiry = 0;
304 // Obtain the idle time we should wait.
305 if (isolate_group_->idle_time_handler()->ShouldNotifyIdle(&idle_expiry)) {
306 MonitorLeaveScope mls(ml);
307 NotifyIdle();
308 return;
309 }
310
311 // Wait for the recommended idle timeout.
312 // We can be woken up because of a), b) or c)
313 const auto result =
314 ml->WaitMicros(idle_expiry - OS::GetCurrentMonotonicMicros());
315
316 // a) If there are new tasks we have to run them.
317 if (TasksWaitingToRunLocked()) return;
318
319 // b) If the thread pool is shutting down we're done.
320 if (ShuttingDownLocked()) return;
321
322 // c) We timed out and should run the idle notifier.
323 if (result == Monitor::kTimedOut &&
324 isolate_group_->idle_time_handler()->ShouldNotifyIdle(&idle_expiry)) {
325 MonitorLeaveScope mls(ml);
326 NotifyIdle();
327 return;
328 }
329
330 // There must've been another thread doing active work in the meantime.
331 // If that thread becomes idle and is the last idle thread it will run this
332 // code again.
333}
334
335void MutatorThreadPool::NotifyIdle() {
336 EnterIsolateGroupScope isolate_group_scope(isolate_group_);
337 isolate_group_->idle_time_handler()->NotifyIdleUsingDefaultDeadline();
338}
339
340IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
341 void* embedder_data,
342 ObjectStore* object_store)
343 : embedder_data_(embedder_data),
344 thread_pool_(),
345 isolates_lock_(new SafepointRwLock()),
346 isolates_(),
347 start_time_micros_(OS::GetCurrentMonotonicMicros()),
348#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
349 last_reload_timestamp_(OS::GetCurrentTimeMillis()),
350#endif
351 source_(std::move(source)),
352 api_state_(new ApiState()),
353 thread_registry_(new ThreadRegistry()),
354 safepoint_handler_(new SafepointHandler(this)),
355 shared_class_table_(new SharedClassTable()),
356 object_store_(object_store),
357#if defined(DART_PRECOMPILED_RUNTIME)
358 class_table_(new ClassTable(shared_class_table_.get())),
359#else
360 class_table_(nullptr),
361#endif
362 store_buffer_(new StoreBuffer()),
363 heap_(nullptr),
364 saved_unlinked_calls_(Array::null()),
365 symbols_lock_(new SafepointRwLock()),
366 type_canonicalization_mutex_(
367 NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
368 type_arguments_canonicalization_mutex_(NOT_IN_PRODUCT(
369 "IsolateGroup::type_arguments_canonicalization_mutex_")),
370 active_mutators_monitor_(new Monitor()),
371 max_active_mutators_(Scavenger::MaxMutatorThreadCount()) {
372 const bool is_vm_isolate = Dart::VmIsolateNameEquals(source_->name);
373 if (!is_vm_isolate) {
374 thread_pool_.reset(
375 new MutatorThreadPool(this, FLAG_disable_thread_pool_limit
376 ? 0
377 : Scavenger::MaxMutatorThreadCount()));
378 }
379 {
380 WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
381 id_ = isolate_group_random_->NextUInt64();
382 }
383}
384
385IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
386 void* embedder_data)
387 : IsolateGroup(source,
388 embedder_data,
389#if !defined(DART_PRECOMPILED_RUNTIME)
390 // in JIT, with --enable_isolate_groups keep object store
391 // on isolate, rather than on isolate group
392 FLAG_enable_isolate_groups ? nullptr :
393#endif
394 new ObjectStore()) {
395 if (object_store() != nullptr) {
396 object_store()->InitStubs();
397 }
398}
399
400IsolateGroup::~IsolateGroup() {
401 // Finalize any weak persistent handles with a non-null referent.
402 FinalizeWeakPersistentHandlesVisitor visitor(this);
403 api_state()->VisitWeakHandlesUnlocked(&visitor);
404
405 // Ensure we destroy the heap before the other members.
406 heap_ = nullptr;
407 ASSERT(marking_stack_ == nullptr);
408}
409
410void IsolateGroup::RegisterIsolate(Isolate* isolate) {
411 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
412 RegisterIsolateLocked(isolate);
413}
414
415void IsolateGroup::RegisterIsolateLocked(Isolate* isolate) {
416 isolates_.Append(isolate);
417 isolate_count_++;
418}
419
420bool IsolateGroup::ContainsOnlyOneIsolate() {
421 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
422 return isolate_count_ == 0;
423}
424
425void IsolateGroup::RunWithLockedGroup(std::function<void()> fun) {
426 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
427 fun();
428}
429
430void IsolateGroup::UnregisterIsolate(Isolate* isolate) {
431 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
432 isolates_.Remove(isolate);
433}
434
435bool IsolateGroup::UnregisterIsolateDecrementCount(Isolate* isolate) {
436 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
437 isolate_count_--;
438 return isolate_count_ == 0;
439}
440
441void IsolateGroup::CreateHeap(bool is_vm_isolate,
442 bool is_service_or_kernel_isolate) {
443 Heap::Init(this,
444 is_vm_isolate
445 ? 0 // New gen size 0; VM isolate should only allocate in old.
446 : FLAG_new_gen_semi_max_size * MBInWords,
447 (is_service_or_kernel_isolate ? kDefaultMaxOldGenHeapSize
448 : FLAG_old_gen_heap_size) *
449 MBInWords);
450
451 is_vm_isolate_heap_ = is_vm_isolate;
452
453#define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit) \
454 metric_##variable##_.InitInstance(this, name, nullptr, Metric::unit);
455 ISOLATE_GROUP_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS)
456#undef ISOLATE_METRIC_CONSTRUCTORS
457}
458
459void IsolateGroup::Shutdown() {
460 // Ensure to join all threads before waiting for pending GC tasks (the thread
461 // pool can trigger idle notification, which can start new GC tasks).
462 //
463 // (The vm-isolate doesn't have a thread pool.)
464 if (!Dart::VmIsolateNameEquals(source()->name)) {
465 ASSERT(thread_pool_ != nullptr);
466 thread_pool_->Shutdown();
467 thread_pool_.reset();
468 }
469
470 // Wait for any pending GC tasks.
471 if (heap_ != nullptr) {
472 // Wait for any concurrent GC tasks to finish before shutting down.
473 // TODO(rmacnak): Interrupt tasks for faster shutdown.
474 PageSpace* old_space = heap_->old_space();
475 MonitorLocker ml(old_space->tasks_lock());
476 while (old_space->tasks() > 0) {
477 ml.Wait();
478 }
479 // Needs to happen before ~PageSpace so TLS and the thread registery are
480 // still valid.
481 old_space->AbandonMarkingForShutdown();
482 }
483
484 UnregisterIsolateGroup(this);
485
486 // If the creation of the isolate group (or the first isolate within the
487 // isolate group) failed, we do not invoke the cleanup callback (the
488 // embedder is responsible for handling the creation error).
489 if (initial_spawn_successful_) {
490 auto group_shutdown_callback = Isolate::GroupCleanupCallback();
491 if (group_shutdown_callback != nullptr) {
492 group_shutdown_callback(embedder_data());
493 }
494 }
495
496 delete this;
497
498 // After this isolate group has died we might need to notify a pending
499 // `Dart_Cleanup()` call.
500 {
501 MonitorLocker ml(Isolate::isolate_creation_monitor_);
502 if (!Isolate::creation_enabled_ &&
503 !IsolateGroup::HasApplicationIsolateGroups()) {
504 ml.Notify();
505 }
506 }
507}
508
509void IsolateGroup::set_heap(std::unique_ptr<Heap> heap) {
510 idle_time_handler_.InitializeWithHeap(heap.get());
511 heap_ = std::move(heap);
512}
513
514void IsolateGroup::set_saved_unlinked_calls(const Array& saved_unlinked_calls) {
515 saved_unlinked_calls_ = saved_unlinked_calls.raw();
516}
517
518Thread* IsolateGroup::ScheduleThreadLocked(MonitorLocker* ml,
519 Thread* existing_mutator_thread,
520 bool is_vm_isolate,
521 bool is_mutator,
522 bool bypass_safepoint) {
523 ASSERT(threads_lock()->IsOwnedByCurrentThread());
524
525 // Schedule the thread into the isolate group by associating
526 // a 'Thread' structure with it (this is done while we are holding
527 // the thread registry lock).
528 Thread* thread = nullptr;
529 OSThread* os_thread = OSThread::Current();
530 if (os_thread != nullptr) {
531 // If a safepoint operation is in progress wait for it
532 // to finish before scheduling this thread in.
533 while (!bypass_safepoint && safepoint_handler()->SafepointInProgress()) {
534 ml->Wait();
535 }
536
537 if (is_mutator) {
538 if (existing_mutator_thread == nullptr) {
539 // Allocate a new [Thread] structure for the mutator thread.
540 thread = thread_registry()->GetFreeThreadLocked(is_vm_isolate);
541 } else {
542 // Reuse the existing cached [Thread] structure for the mutator thread.,
543 // see comment in 'base_isolate.h'.
544 thread_registry()->AddToActiveListLocked(existing_mutator_thread);
545 thread = existing_mutator_thread;
546 }
547 } else {
548 thread = thread_registry()->GetFreeThreadLocked(is_vm_isolate);
549 }
550
551 // Now get a free Thread structure.
552 ASSERT(thread != nullptr);
553
554 thread->ResetHighWatermark();
555
556 // Set up other values and set the TLS value.
557 thread->isolate_ = nullptr;
558 thread->isolate_group_ = this;
559 thread->field_table_values_ = nullptr;
560 ASSERT(heap() != nullptr);
561 thread->heap_ = heap();
562 thread->set_os_thread(os_thread);
563 ASSERT(thread->execution_state() == Thread::kThreadInNative);
564 thread->set_execution_state(Thread::kThreadInVM);
565 thread->set_safepoint_state(
566 Thread::SetBypassSafepoints(bypass_safepoint, 0));
567 thread->set_vm_tag(VMTag::kVMTagId);
568 ASSERT(thread->no_safepoint_scope_depth() == 0);
569 os_thread->set_thread(thread);
570 Thread::SetCurrent(thread);
571 os_thread->EnableThreadInterrupts();
572 }
573 return thread;
574}
575
576void IsolateGroup::UnscheduleThreadLocked(MonitorLocker* ml,
577 Thread* thread,
578 bool is_mutator,
579 bool bypass_safepoint) {
580 thread->heap()->new_space()->AbandonRemainingTLAB(thread);
581
582 // Clear since GC will not visit the thread once it is unscheduled. Do this
583 // under the thread lock to prevent races with the GC visiting thread roots.
584 if (!is_mutator) {
585 thread->ClearReusableHandles();
586 }
587
588 // Disassociate the 'Thread' structure and unschedule the thread
589 // from this isolate group.
590 if (!is_mutator) {
591 ASSERT(thread->api_top_scope_ == nullptr);
592 ASSERT(thread->zone() == nullptr);
593 ASSERT(thread->sticky_error() == Error::null());
594 }
595 if (!bypass_safepoint) {
596 // Ensure that the thread reports itself as being at a safepoint.
597 thread->EnterSafepoint();
598 }
599 OSThread* os_thread = thread->os_thread();
600 ASSERT(os_thread != nullptr);
601 os_thread->DisableThreadInterrupts();
602 os_thread->set_thread(nullptr);
603 OSThread::SetCurrent(os_thread);
604
605 // Even if we unschedule the mutator thread, e.g. via calling
606 // `Dart_ExitIsolate()` inside a native, we might still have one or more Dart
607 // stacks active, which e.g. GC marker threads want to visit. So we don't
608 // clear out the isolate pointer if we are on the mutator thread.
609 //
610 // The [thread] structure for the mutator thread is kept alive in the thread
611 // registry even if the mutator thread is temporarily unscheduled.
612 //
613 // All other threads are not allowed to unschedule themselves and schedule
614 // again later on.
615 if (!is_mutator) {
616 ASSERT(thread->isolate_ == nullptr);
617 thread->isolate_group_ = nullptr;
618 }
619 thread->heap_ = nullptr;
620 thread->set_os_thread(nullptr);
621 thread->set_execution_state(Thread::kThreadInNative);
622 thread->set_safepoint_state(Thread::SetAtSafepoint(true, 0));
623 thread->clear_pending_functions();
624 ASSERT(thread->no_safepoint_scope_depth() == 0);
625 if (is_mutator) {
626 // The mutator thread structure stays alive and attached to the isolate as
627 // long as the isolate lives. So we simply remove the thread from the list
628 // of scheduled threads.
629 thread_registry()->RemoveFromActiveListLocked(thread);
630 } else {
631 // Return thread structure.
632 thread_registry()->ReturnThreadLocked(thread);
633 }
634}
635
636Thread* IsolateGroup::ScheduleThread(bool bypass_safepoint) {
637 // We are about to associate the thread with an isolate group and it would
638 // not be possible to correctly track no_safepoint_scope_depth for the
639 // thread in the constructor/destructor of MonitorLocker,
640 // so we create a MonitorLocker object which does not do any
641 // no_safepoint_scope_depth increments/decrements.
642 MonitorLocker ml(threads_lock(), false);
643
644 const bool is_vm_isolate = false;
645
646 // Schedule the thread into the isolate by associating
647 // a 'Thread' structure with it (this is done while we are holding
648 // the thread registry lock).
649 return ScheduleThreadLocked(&ml, /*existing_mutator_thread=*/nullptr,
650 is_vm_isolate, /*is_mutator=*/false,
651 bypass_safepoint);
652}
653
654void IsolateGroup::UnscheduleThread(Thread* thread,
655 bool is_mutator,
656 bool bypass_safepoint) {
657 // Disassociate the 'Thread' structure and unschedule the thread
658 // from this isolate group.
659 //
660 // We are disassociating the thread from an isolate and it would
661 // not be possible to correctly track no_safepoint_scope_depth for the
662 // thread in the constructor/destructor of MonitorLocker,
663 // so we create a MonitorLocker object which does not do any
664 // no_safepoint_scope_depth increments/decrements.
665 MonitorLocker ml(threads_lock(), false);
666 UnscheduleThreadLocked(&ml, thread, is_mutator, bypass_safepoint);
667}
668
669void IsolateGroup::IncreaseMutatorCount(Isolate* mutator) {
670 ASSERT(mutator->group() == this);
671
672 // If the mutator was temporarily blocked on a worker thread, we have to
673 // unblock the worker thread again.
674 Thread* mutator_thread = mutator->mutator_thread();
675 if (mutator_thread != nullptr && mutator_thread->top_exit_frame_info() != 0) {
676 thread_pool()->MarkCurrentWorkerAsUnBlocked();
677 }
678
679 // Prevent too many mutators from entering the isolate group to avoid
680 // pathological behavior where many threads are fighting for obtaining TLABs.
681 {
682 // NOTE: This is performance critical code, we should avoid monitors and use
683 // std::atomics in the fast case (where active_mutators <
684 // max_active_mutators) and only use montiors in the uncommon case.
685 MonitorLocker ml(active_mutators_monitor_.get());
686 ASSERT(active_mutators_ <= max_active_mutators_);
687 while (active_mutators_ == max_active_mutators_) {
688 waiting_mutators_++;
689 ml.Wait();
690 waiting_mutators_--;
691 }
692 active_mutators_++;
693 }
694}
695
696void IsolateGroup::DecreaseMutatorCount(Isolate* mutator) {
697 ASSERT(mutator->group() == this);
698
699 // If the mutator thread has an active stack and runs on our thread pool we
700 // will mark the worker as blocked, thereby possibly spawning a new worker for
701 // pending tasks (if there are any).
702 Thread* mutator_thread = mutator->mutator_thread();
703 ASSERT(mutator_thread != nullptr);
704 if (mutator_thread->top_exit_frame_info() != 0) {
705 thread_pool()->MarkCurrentWorkerAsBlocked();
706 }
707
708 {
709 // NOTE: This is performance critical code, we should avoid monitors and use
710 // std::atomics in the fast case (where active_mutators <
711 // max_active_mutators) and only use montiors in the uncommon case.
712 MonitorLocker ml(active_mutators_monitor_.get());
713 ASSERT(active_mutators_ <= max_active_mutators_);
714 active_mutators_--;
715 if (waiting_mutators_ > 0) {
716 ml.Notify();
717 }
718 }
719}
720
721#ifndef PRODUCT
722void IsolateGroup::PrintJSON(JSONStream* stream, bool ref) {
723 JSONObject jsobj(stream);
724 PrintToJSONObject(&jsobj, ref);
725}
726
727void IsolateGroup::PrintToJSONObject(JSONObject* jsobj, bool ref) {
728 jsobj->AddProperty("type", (ref ? "@IsolateGroup" : "IsolateGroup"));
729 jsobj->AddServiceId(ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING, id());
730
731 jsobj->AddProperty("name", source()->script_uri);
732 jsobj->AddPropertyF("number", "%" Pu64 "", id());
733 if (ref) {
734 return;
735 }
736
737 {
738 JSONArray isolate_array(jsobj, "isolates");
739 for (auto it = isolates_.Begin(); it != isolates_.End(); ++it) {
740 Isolate* isolate = *it;
741 isolate_array.AddValue(isolate, /*ref=*/true);
742 }
743 }
744}
745
746void IsolateGroup::PrintMemoryUsageJSON(JSONStream* stream) {
747 int64_t used = 0;
748 int64_t capacity = 0;
749 int64_t external_used = 0;
750
751 for (auto it = isolates_.Begin(); it != isolates_.End(); ++it) {
752 Isolate* isolate = *it;
753 used += isolate->heap()->TotalUsedInWords();
754 capacity += isolate->heap()->TotalCapacityInWords();
755 external_used += isolate->heap()->TotalExternalInWords();
756 }
757
758 JSONObject jsobj(stream);
759 // This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
760 // rpc method returns.
761 // TODO(dartbug.com/36097): Once the heap moves from Isolate to IsolateGroup
762 // this code needs to be adjusted to not double-count memory.
763 jsobj.AddProperty("type", "MemoryUsage");
764 jsobj.AddProperty64("heapUsage", used * kWordSize);
765 jsobj.AddProperty64("heapCapacity", capacity * kWordSize);
766 jsobj.AddProperty64("externalUsage", external_used * kWordSize);
767}
768#endif
769
770void IsolateGroup::ForEach(std::function<void(IsolateGroup*)> action) {
771 ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
772 for (auto isolate_group : *isolate_groups_) {
773 action(isolate_group);
774 }
775}
776
777void IsolateGroup::RunWithIsolateGroup(
778 uint64_t id,
779 std::function<void(IsolateGroup*)> action,
780 std::function<void()> not_found) {
781 ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
782 for (auto isolate_group : *isolate_groups_) {
783 if (isolate_group->id() == id) {
784 action(isolate_group);
785 return;
786 }
787 }
788 not_found();
789}
790
791void IsolateGroup::RegisterIsolateGroup(IsolateGroup* isolate_group) {
792 WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
793 isolate_groups_->Append(isolate_group);
794}
795
796void IsolateGroup::UnregisterIsolateGroup(IsolateGroup* isolate_group) {
797 WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
798 isolate_groups_->Remove(isolate_group);
799}
800
801bool IsolateGroup::HasApplicationIsolateGroups() {
802 ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
803 for (auto group : *isolate_groups_) {
804 if (!IsolateGroup::IsVMInternalIsolateGroup(group)) {
805 return true;
806 }
807 }
808 return false;
809}
810
811bool IsolateGroup::HasOnlyVMIsolateGroup() {
812 ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
813 for (auto group : *isolate_groups_) {
814 if (!Dart::VmIsolateNameEquals(group->source()->name)) {
815 return false;
816 }
817 }
818 return true;
819}
820
821void IsolateGroup::Init() {
822 ASSERT(isolate_groups_rwlock_ == nullptr);
823 isolate_groups_rwlock_ = new RwLock();
824 ASSERT(isolate_groups_ == nullptr);
825 isolate_groups_ = new IntrusiveDList<IsolateGroup>();
826 isolate_group_random_ = new Random();
827}
828
829void IsolateGroup::Cleanup() {
830 delete isolate_group_random_;
831 isolate_group_random_ = nullptr;
832 delete isolate_groups_rwlock_;
833 isolate_groups_rwlock_ = nullptr;
834 ASSERT(isolate_groups_->IsEmpty());
835 delete isolate_groups_;
836 isolate_groups_ = nullptr;
837}
838
839bool IsolateVisitor::IsVMInternalIsolate(Isolate* isolate) const {
840 return Isolate::IsVMInternalIsolate(isolate);
841}
842
843NoOOBMessageScope::NoOOBMessageScope(Thread* thread)
844 : ThreadStackResource(thread) {
845 thread->DeferOOBMessageInterrupts();
846}
847
848NoOOBMessageScope::~NoOOBMessageScope() {
849 thread()->RestoreOOBMessageInterrupts();
850}
851
852NoReloadScope::NoReloadScope(Isolate* isolate, Thread* thread)
853 : ThreadStackResource(thread), isolate_(isolate) {
854#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
855 ASSERT(isolate_ != NULL);
856 isolate_->no_reload_scope_depth_.fetch_add(1);
857 ASSERT(isolate_->no_reload_scope_depth_ >= 0);
858#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
859}
860
861NoReloadScope::~NoReloadScope() {
862#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
863 isolate_->no_reload_scope_depth_.fetch_sub(1);
864 ASSERT(isolate_->no_reload_scope_depth_ >= 0);
865#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
866}
867
868Bequest::~Bequest() {
869 IsolateGroup* isolate_group = IsolateGroup::Current();
870 CHECK_ISOLATE_GROUP(isolate_group);
871 NoSafepointScope no_safepoint_scope;
872 ApiState* state = isolate_group->api_state();
873 ASSERT(state != nullptr);
874 state->FreePersistentHandle(handle_);
875}
876
877void Isolate::RegisterClass(const Class& cls) {
878#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
879 if (group()->IsReloading()) {
880 reload_context()->RegisterClass(cls);
881 return;
882 }
883#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
884 if (cls.IsTopLevel()) {
885 class_table()->RegisterTopLevel(cls);
886 } else {
887 class_table()->Register(cls);
888 }
889}
890
891#if defined(DEBUG)
892void Isolate::ValidateClassTable() {
893 class_table()->Validate();
894}
895#endif // DEBUG
896
897void Isolate::RegisterStaticField(const Field& field) {
898 field_table()->Register(field);
899}
900
901void Isolate::RehashConstants() {
902 Thread* thread = Thread::Current();
903 StackZone stack_zone(thread);
904 Zone* zone = stack_zone.GetZone();
905
906 thread->heap()->ResetCanonicalHashTable();
907
908 Class& cls = Class::Handle(zone);
909 intptr_t top = class_table()->NumCids();
910 for (intptr_t cid = kInstanceCid; cid < top; cid++) {
911 if (!class_table()->IsValidIndex(cid) ||
912 !class_table()->HasValidClassAt(cid)) {
913 continue;
914 }
915 if ((cid == kTypeArgumentsCid) || IsStringClassId(cid)) {
916 // TypeArguments and Symbols have special tables for canonical objects
917 // that aren't based on address.
918 continue;
919 }
920 cls = class_table()->At(cid);
921 cls.RehashConstants(zone);
922 }
923}
924
925#if defined(DEBUG)
926void Isolate::ValidateConstants() {
927 if (FLAG_precompiled_mode) {
928 // TODO(27003)
929 return;
930 }
931 if (HasAttemptedReload()) {
932 return;
933 }
934 // Verify that all canonical instances are correctly setup in the
935 // corresponding canonical tables.
936 BackgroundCompiler::Stop(this);
937 heap()->CollectAllGarbage();
938 Thread* thread = Thread::Current();
939 HeapIterationScope iteration(thread);
940 VerifyCanonicalVisitor check_canonical(thread);
941 iteration.IterateObjects(&check_canonical);
942}
943#endif // DEBUG
944
945void Isolate::SendInternalLibMessage(LibMsgId msg_id, uint64_t capability) {
946 const Array& msg = Array::Handle(Array::New(3));
947 Object& element = Object::Handle();
948
949 element = Smi::New(Message::kIsolateLibOOBMsg);
950 msg.SetAt(0, element);
951 element = Smi::New(msg_id);
952 msg.SetAt(1, element);
953 element = Capability::New(capability);
954 msg.SetAt(2, element);
955
956 MessageWriter writer(false);
957 PortMap::PostMessage(
958 writer.WriteMessage(msg, main_port(), Message::kOOBPriority));
959}
960
961void Isolate::set_object_store(ObjectStore* object_store) {
962 ASSERT(cached_object_store_ == nullptr);
963 object_store_shared_ptr_.reset(object_store);
964 cached_object_store_ = object_store;
965 isolate_object_store_->set_object_store(object_store);
966}
967
968class IsolateMessageHandler : public MessageHandler {
969 public:
970 explicit IsolateMessageHandler(Isolate* isolate);
971 ~IsolateMessageHandler();
972
973 const char* name() const;
974 void MessageNotify(Message::Priority priority);
975 MessageStatus HandleMessage(std::unique_ptr<Message> message);
976#ifndef PRODUCT
977 void NotifyPauseOnStart();
978 void NotifyPauseOnExit();
979#endif // !PRODUCT
980
981#if defined(DEBUG)
982 // Check that it is safe to access this handler.
983 void CheckAccess();
984#endif
985 bool IsCurrentIsolate() const;
986 virtual Isolate* isolate() const { return isolate_; }
987
988 private:
989 // A result of false indicates that the isolate should terminate the
990 // processing of further events.
991 ErrorPtr HandleLibMessage(const Array& message);
992
993 MessageStatus ProcessUnhandledException(const Error& result);
994 Isolate* isolate_;
995};
996
997IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate)
998 : isolate_(isolate) {}
999
1000IsolateMessageHandler::~IsolateMessageHandler() {}
1001
1002const char* IsolateMessageHandler::name() const {
1003 return isolate_->name();
1004}
1005
1006// Isolate library OOB messages are fixed sized arrays which have the
1007// following format:
1008// [ OOB dispatch, Isolate library dispatch, <message specific data> ]
1009ErrorPtr IsolateMessageHandler::HandleLibMessage(const Array& message) {
1010 if (message.Length() < 2) return Error::null();
1011 Zone* zone = T->zone();
1012 const Object& type = Object::Handle(zone, message.At(1));
1013 if (!type.IsSmi()) return Error::null();
1014 const intptr_t msg_type = Smi::Cast(type).Value();
1015 switch (msg_type) {
1016 case Isolate::kPauseMsg: {
1017 // [ OOB, kPauseMsg, pause capability, resume capability ]
1018 if (message.Length() != 4) return Error::null();
1019 Object& obj = Object::Handle(zone, message.At(2));
1020 if (!I->VerifyPauseCapability(obj)) return Error::null();
1021 obj = message.At(3);
1022 if (!obj.IsCapability()) return Error::null();
1023 if (I->AddResumeCapability(Capability::Cast(obj))) {
1024 increment_paused();
1025 }
1026 break;
1027 }
1028 case Isolate::kResumeMsg: {
1029 // [ OOB, kResumeMsg, pause capability, resume capability ]
1030 if (message.Length() != 4) return Error::null();
1031 Object& obj = Object::Handle(zone, message.At(2));
1032 if (!I->VerifyPauseCapability(obj)) return Error::null();
1033 obj = message.At(3);
1034 if (!obj.IsCapability()) return Error::null();
1035 if (I->RemoveResumeCapability(Capability::Cast(obj))) {
1036 decrement_paused();
1037 }
1038 break;
1039 }
1040 case Isolate::kPingMsg: {
1041 // [ OOB, kPingMsg, responsePort, priority, response ]
1042 if (message.Length() != 5) return Error::null();
1043 const Object& obj2 = Object::Handle(zone, message.At(2));
1044 if (!obj2.IsSendPort()) return Error::null();
1045 const SendPort& send_port = SendPort::Cast(obj2);
1046 const Object& obj3 = Object::Handle(zone, message.At(3));
1047 if (!obj3.IsSmi()) return Error::null();
1048 const intptr_t priority = Smi::Cast(obj3).Value();
1049 const Object& obj4 = Object::Handle(zone, message.At(4));
1050 if (!obj4.IsInstance() && !obj4.IsNull()) return Error::null();
1051 const Instance& response =
1052 obj4.IsNull() ? Instance::null_instance() : Instance::Cast(obj4);
1053 if (priority == Isolate::kImmediateAction) {
1054 PortMap::PostMessage(SerializeMessage(send_port.Id(), response));
1055 } else {
1056 ASSERT((priority == Isolate::kBeforeNextEventAction) ||
1057 (priority == Isolate::kAsEventAction));
1058 // Update the message so that it will be handled immediately when it
1059 // is picked up from the message queue the next time.
1060 message.SetAt(
1061 0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
1062 message.SetAt(3,
1063 Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
1064 this->PostMessage(
1065 SerializeMessage(Message::kIllegalPort, message),
1066 priority == Isolate::kBeforeNextEventAction /* at_head */);
1067 }
1068 break;
1069 }
1070 case Isolate::kKillMsg:
1071 case Isolate::kInternalKillMsg: {
1072 // [ OOB, kKillMsg, terminate capability, priority ]
1073 if (message.Length() != 4) return Error::null();
1074 Object& obj = Object::Handle(zone, message.At(3));
1075 if (!obj.IsSmi()) return Error::null();
1076 const intptr_t priority = Smi::Cast(obj).Value();
1077 if (priority == Isolate::kImmediateAction) {
1078 obj = message.At(2);
1079 if (I->VerifyTerminateCapability(obj)) {
1080 // We will kill the current isolate by returning an UnwindError.
1081 if (msg_type == Isolate::kKillMsg) {
1082 const String& msg = String::Handle(
1083 String::New("isolate terminated by Isolate.kill"));
1084 const UnwindError& error =
1085 UnwindError::Handle(UnwindError::New(msg));
1086 error.set_is_user_initiated(true);
1087 return error.raw();
1088 } else if (msg_type == Isolate::kInternalKillMsg) {
1089 const String& msg =
1090 String::Handle(String::New("isolate terminated by vm"));
1091 return UnwindError::New(msg);
1092 } else {
1093 UNREACHABLE();
1094 }
1095 } else {
1096 return Error::null();
1097 }
1098 } else {
1099 ASSERT((priority == Isolate::kBeforeNextEventAction) ||
1100 (priority == Isolate::kAsEventAction));
1101 // Update the message so that it will be handled immediately when it
1102 // is picked up from the message queue the next time.
1103 message.SetAt(
1104 0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
1105 message.SetAt(3,
1106 Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
1107 this->PostMessage(
1108 SerializeMessage(Message::kIllegalPort, message),
1109 priority == Isolate::kBeforeNextEventAction /* at_head */);
1110 }
1111 break;
1112 }
1113 case Isolate::kInterruptMsg: {
1114 // [ OOB, kInterruptMsg, pause capability ]
1115 if (message.Length() != 3) return Error::null();
1116 Object& obj = Object::Handle(zone, message.At(2));
1117 if (!I->VerifyPauseCapability(obj)) return Error::null();
1118
1119#if !defined(PRODUCT)
1120 // If we are already paused, don't pause again.
1121 if (I->debugger()->PauseEvent() == NULL) {
1122 return I->debugger()->PauseInterrupted();
1123 }
1124#endif
1125 break;
1126 }
1127 case Isolate::kLowMemoryMsg: {
1128 I->heap()->NotifyLowMemory();
1129 break;
1130 }
1131 case Isolate::kDrainServiceExtensionsMsg: {
1132#ifndef PRODUCT
1133 Object& obj = Object::Handle(zone, message.At(2));
1134 if (!obj.IsSmi()) return Error::null();
1135 const intptr_t priority = Smi::Cast(obj).Value();
1136 if (priority == Isolate::kImmediateAction) {
1137 return I->InvokePendingServiceExtensionCalls();
1138 } else {
1139 ASSERT((priority == Isolate::kBeforeNextEventAction) ||
1140 (priority == Isolate::kAsEventAction));
1141 // Update the message so that it will be handled immediately when it
1142 // is picked up from the message queue the next time.
1143 message.SetAt(
1144 0, Smi::Handle(zone, Smi::New(Message::kDelayedIsolateLibOOBMsg)));
1145 message.SetAt(2,
1146 Smi::Handle(zone, Smi::New(Isolate::kImmediateAction)));
1147 this->PostMessage(
1148 SerializeMessage(Message::kIllegalPort, message),
1149 priority == Isolate::kBeforeNextEventAction /* at_head */);
1150 }
1151#else
1152 UNREACHABLE();
1153#endif // !PRODUCT
1154 break;
1155 }
1156
1157 case Isolate::kAddExitMsg:
1158 case Isolate::kDelExitMsg:
1159 case Isolate::kAddErrorMsg:
1160 case Isolate::kDelErrorMsg: {
1161 // [ OOB, msg, listener port ]
1162 if (message.Length() < 3) return Error::null();
1163 const Object& obj = Object::Handle(zone, message.At(2));
1164 if (!obj.IsSendPort()) return Error::null();
1165 const SendPort& listener = SendPort::Cast(obj);
1166 switch (msg_type) {
1167 case Isolate::kAddExitMsg: {
1168 if (message.Length() != 4) return Error::null();
1169 // [ OOB, msg, listener port, response object ]
1170 const Object& response = Object::Handle(zone, message.At(3));
1171 if (!response.IsInstance() && !response.IsNull()) {
1172 return Error::null();
1173 }
1174 I->AddExitListener(listener, response.IsNull()
1175 ? Instance::null_instance()
1176 : Instance::Cast(response));
1177 break;
1178 }
1179 case Isolate::kDelExitMsg:
1180 if (message.Length() != 3) return Error::null();
1181 I->RemoveExitListener(listener);
1182 break;
1183 case Isolate::kAddErrorMsg:
1184 if (message.Length() != 3) return Error::null();
1185 I->AddErrorListener(listener);
1186 break;
1187 case Isolate::kDelErrorMsg:
1188 if (message.Length() != 3) return Error::null();
1189 I->RemoveErrorListener(listener);
1190 break;
1191 default:
1192 UNREACHABLE();
1193 }
1194 break;
1195 }
1196 case Isolate::kErrorFatalMsg: {
1197 // [ OOB, kErrorFatalMsg, terminate capability, val ]
1198 if (message.Length() != 4) return Error::null();
1199 // Check that the terminate capability has been passed correctly.
1200 Object& obj = Object::Handle(zone, message.At(2));
1201 if (!I->VerifyTerminateCapability(obj)) return Error::null();
1202 // Get the value to be set.
1203 obj = message.At(3);
1204 if (!obj.IsBool()) return Error::null();
1205 I->SetErrorsFatal(Bool::Cast(obj).value());
1206 break;
1207 }
1208#if defined(DEBUG)
1209 // Malformed OOB messages are silently ignored in release builds.
1210 default:
1211 FATAL1("Unknown OOB message type: %" Pd "\n", msg_type);
1212 break;
1213#endif // defined(DEBUG)
1214 }
1215 return Error::null();
1216}
1217
1218void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
1219 if (priority >= Message::kOOBPriority) {
1220 // Handle out of band messages even if the mutator thread is busy.
1221 I->ScheduleInterrupts(Thread::kMessageInterrupt);
1222 }
1223 Dart_MessageNotifyCallback callback = I->message_notify_callback();
1224 if (callback != nullptr) {
1225 // Allow the embedder to handle message notification.
1226 (*callback)(Api::CastIsolate(I));
1227 }
1228}
1229
1230bool Isolate::HasPendingMessages() {
1231 return message_handler_->HasMessages() || message_handler_->HasOOBMessages();
1232}
1233
1234MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
1235 std::unique_ptr<Message> message) {
1236 ASSERT(IsCurrentIsolate());
1237 Thread* thread = Thread::Current();
1238 StackZone stack_zone(thread);
1239 Zone* zone = stack_zone.GetZone();
1240 HandleScope handle_scope(thread);
1241#if defined(SUPPORT_TIMELINE)
1242 TimelineBeginEndScope tbes(
1243 thread, Timeline::GetIsolateStream(),
1244 message->IsOOB() ? "HandleOOBMessage" : "HandleMessage");
1245 tbes.SetNumArguments(1);
1246 tbes.CopyArgument(0, "isolateName", I->name());
1247#endif
1248
1249 // If the message is in band we lookup the handler to dispatch to. If the
1250 // receive port was closed, we drop the message without deserializing it.
1251 // Illegal port is a special case for artificially enqueued isolate library
1252 // messages which are handled in C++ code below.
1253 Object& msg_handler = Object::Handle(zone);
1254 if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) {
1255 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port());
1256 if (msg_handler.IsError()) {
1257 return ProcessUnhandledException(Error::Cast(msg_handler));
1258 }
1259 if (msg_handler.IsNull()) {
1260 // If the port has been closed then the message will be dropped at this
1261 // point. Make sure to post to the delivery failure port in that case.
1262 if (message->RedirectToDeliveryFailurePort()) {
1263 PortMap::PostMessage(std::move(message));
1264 }
1265 return kOK;
1266 }
1267 }
1268
1269 // Parse the message.
1270 Object& msg_obj = Object::Handle(zone);
1271 if (message->IsRaw()) {
1272 msg_obj = message->raw_obj();
1273 // We should only be sending RawObjects that can be converted to CObjects.
1274 ASSERT(ApiObjectConverter::CanConvert(msg_obj.raw()));
1275 } else if (message->IsBequest()) {
1276 Bequest* bequest = message->bequest();
1277 PersistentHandle* handle = bequest->handle();
1278 const Object& obj = Object::Handle(zone, handle->raw());
1279 msg_obj = obj.raw();
1280 } else {
1281 MessageSnapshotReader reader(message.get(), thread);
1282 msg_obj = reader.ReadObject();
1283 }
1284 if (msg_obj.IsError()) {
1285 // An error occurred while reading the message.
1286 return ProcessUnhandledException(Error::Cast(msg_obj));
1287 }
1288 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) {
1289 // TODO(turnidge): We need to decide what an isolate does with
1290 // malformed messages. If they (eventually) come from a remote
1291 // machine, then it might make sense to drop the message entirely.
1292 // In the case that the message originated locally, which is
1293 // always true for now, then this should never occur.
1294 UNREACHABLE();
1295 }
1296 Instance& msg = Instance::Handle(zone);
1297 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null.
1298
1299 MessageStatus status = kOK;
1300 if (message->IsOOB()) {
1301 // OOB messages are expected to be fixed length arrays where the first
1302 // element is a Smi describing the OOB destination. Messages that do not
1303 // confirm to this layout are silently ignored.
1304 if (msg.IsArray()) {
1305 const Array& oob_msg = Array::Cast(msg);
1306 if (oob_msg.Length() > 0) {
1307 const Object& oob_tag = Object::Handle(zone, oob_msg.At(0));
1308 if (oob_tag.IsSmi()) {
1309 switch (Smi::Cast(oob_tag).Value()) {
1310 case Message::kServiceOOBMsg: {
1311#ifndef PRODUCT
1312 const Error& error =
1313 Error::Handle(Service::HandleIsolateMessage(I, oob_msg));
1314 if (!error.IsNull()) {
1315 status = ProcessUnhandledException(error);
1316 }
1317#else
1318 UNREACHABLE();
1319#endif
1320 break;
1321 }
1322 case Message::kIsolateLibOOBMsg: {
1323 const Error& error = Error::Handle(HandleLibMessage(oob_msg));
1324 if (!error.IsNull()) {
1325 status = ProcessUnhandledException(error);
1326 }
1327 break;
1328 }
1329#if defined(DEBUG)
1330 // Malformed OOB messages are silently ignored in release builds.
1331 default: {
1332 UNREACHABLE();
1333 break;
1334 }
1335#endif // defined(DEBUG)
1336 }
1337 }
1338 }
1339 }
1340 } else if (message->dest_port() == Message::kIllegalPort) {
1341 // Check whether this is a delayed OOB message which needed handling as
1342 // part of the regular message dispatch. All other messages are dropped on
1343 // the floor.
1344 if (msg.IsArray()) {
1345 const Array& msg_arr = Array::Cast(msg);
1346 if (msg_arr.Length() > 0) {
1347 const Object& oob_tag = Object::Handle(zone, msg_arr.At(0));
1348 if (oob_tag.IsSmi() &&
1349 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) {
1350 const Error& error = Error::Handle(HandleLibMessage(msg_arr));
1351 if (!error.IsNull()) {
1352 status = ProcessUnhandledException(error);
1353 }
1354 }
1355 }
1356 }
1357 } else {
1358#ifndef PRODUCT
1359 if (!Isolate::IsVMInternalIsolate(I)) {
1360 // Mark all the user isolates as using a simplified timeline page of
1361 // Observatory. The internal isolates will be filtered out from
1362 // the Timeline due to absence of this argument. We still send them in
1363 // order to maintain the original behavior of the full timeline and allow
1364 // the developer to download complete dump files.
1365 tbes.SetNumArguments(2);
1366 tbes.CopyArgument(1, "mode", "basic");
1367 }
1368#endif
1369 const Object& result =
1370 Object::Handle(zone, DartLibraryCalls::HandleMessage(msg_handler, msg));
1371 if (result.IsError()) {
1372 status = ProcessUnhandledException(Error::Cast(result));
1373 } else {
1374 ASSERT(result.IsNull());
1375 }
1376 }
1377 return status;
1378}
1379
1380#ifndef PRODUCT
1381void IsolateMessageHandler::NotifyPauseOnStart() {
1382 if (Isolate::IsVMInternalIsolate(I)) {
1383 return;
1384 }
1385 if (Service::debug_stream.enabled() || FLAG_warn_on_pause_with_no_debugger) {
1386 StartIsolateScope start_isolate(I);
1387 StackZone zone(T);
1388 HandleScope handle_scope(T);
1389 ServiceEvent pause_event(I, ServiceEvent::kPauseStart);
1390 Service::HandleEvent(&pause_event);
1391 } else if (FLAG_trace_service) {
1392 OS::PrintErr("vm-service: Dropping event of type PauseStart (%s)\n",
1393 I->name());
1394 }
1395}
1396
1397void IsolateMessageHandler::NotifyPauseOnExit() {
1398 if (Isolate::IsVMInternalIsolate(I)) {
1399 return;
1400 }
1401 if (Service::debug_stream.enabled() || FLAG_warn_on_pause_with_no_debugger) {
1402 StartIsolateScope start_isolate(I);
1403 StackZone zone(T);
1404 HandleScope handle_scope(T);
1405 ServiceEvent pause_event(I, ServiceEvent::kPauseExit);
1406 Service::HandleEvent(&pause_event);
1407 } else if (FLAG_trace_service) {
1408 OS::PrintErr("vm-service: Dropping event of type PauseExit (%s)\n",
1409 I->name());
1410 }
1411}
1412#endif // !PRODUCT
1413
1414#if defined(DEBUG)
1415void IsolateMessageHandler::CheckAccess() {
1416 ASSERT(IsCurrentIsolate());
1417}
1418#endif
1419
1420bool IsolateMessageHandler::IsCurrentIsolate() const {
1421 return (I == Isolate::Current());
1422}
1423
1424static MessageHandler::MessageStatus StoreError(Thread* thread,
1425 const Error& error) {
1426 thread->set_sticky_error(error);
1427 if (error.IsUnwindError()) {
1428 const UnwindError& unwind = UnwindError::Cast(error);
1429 if (!unwind.is_user_initiated()) {
1430 return MessageHandler::kShutdown;
1431 }
1432 }
1433 return MessageHandler::kError;
1434}
1435
1436MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
1437 const Error& result) {
1438 if (FLAG_trace_isolates) {
1439 OS::PrintErr(
1440 "[!] Unhandled exception in %s:\n"
1441 " exception: %s\n",
1442 T->isolate()->name(), result.ToErrorCString());
1443 }
1444
1445 NoReloadScope no_reload_scope(T->isolate(), T);
1446 // Generate the error and stacktrace strings for the error message.
1447 String& exc_str = String::Handle(T->zone());
1448 String& stacktrace_str = String::Handle(T->zone());
1449 if (result.IsUnhandledException()) {
1450 Zone* zone = T->zone();
1451 const UnhandledException& uhe = UnhandledException::Cast(result);
1452 const Instance& exception = Instance::Handle(zone, uhe.exception());
1453 Object& tmp = Object::Handle(zone);
1454 tmp = DartLibraryCalls::ToString(exception);
1455 if (!tmp.IsString()) {
1456 tmp = String::New(exception.ToCString());
1457 }
1458 exc_str ^= tmp.raw();
1459
1460 const Instance& stacktrace = Instance::Handle(zone, uhe.stacktrace());
1461 tmp = DartLibraryCalls::ToString(stacktrace);
1462 if (!tmp.IsString()) {
1463 tmp = String::New(stacktrace.ToCString());
1464 }
1465 stacktrace_str ^= tmp.raw();
1466 } else {
1467 exc_str = String::New(result.ToErrorCString());
1468 }
1469 if (result.IsUnwindError()) {
1470 // When unwinding we don't notify error listeners and we ignore
1471 // whether errors are fatal for the current isolate.
1472 return StoreError(T, result);
1473 } else {
1474 bool has_listener = I->NotifyErrorListeners(exc_str, stacktrace_str);
1475 if (I->ErrorsFatal()) {
1476 if (has_listener) {
1477 T->ClearStickyError();
1478 } else {
1479 T->set_sticky_error(result);
1480 }
1481#if !defined(PRODUCT)
1482 // Notify the debugger about specific unhandled exceptions which are
1483 // withheld when being thrown. Do this after setting the sticky error
1484 // so the isolate has an error set when paused with the unhandled
1485 // exception.
1486 if (result.IsUnhandledException()) {
1487 const UnhandledException& error = UnhandledException::Cast(result);
1488 InstancePtr exception = error.exception();
1489 if ((exception == I->object_store()->out_of_memory()) ||
1490 (exception == I->object_store()->stack_overflow())) {
1491 // We didn't notify the debugger when the stack was full. Do it now.
1492 I->debugger()->PauseException(Instance::Handle(exception));
1493 }
1494 }
1495#endif // !defined(PRODUCT)
1496 return kError;
1497 }
1498 }
1499 return kOK;
1500}
1501
1502void Isolate::FlagsInitialize(Dart_IsolateFlags* api_flags) {
1503 const bool false_by_default = false;
1504 const bool true_by_default = true;
1505 USE(true_by_default);
1506 USE(false_by_default);
1507
1508 api_flags->version = DART_FLAGS_CURRENT_VERSION;
1509#define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag) \
1510 api_flags->isolate_flag = flag;
1511 ISOLATE_FLAG_LIST(INIT_FROM_FLAG)
1512#undef INIT_FROM_FLAG
1513 api_flags->entry_points = NULL;
1514 api_flags->load_vmservice_library = false;
1515 api_flags->copy_parent_code = false;
1516 api_flags->null_safety = false;
1517}
1518
1519void Isolate::FlagsCopyTo(Dart_IsolateFlags* api_flags) const {
1520 api_flags->version = DART_FLAGS_CURRENT_VERSION;
1521#define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag) \
1522 api_flags->isolate_flag = name();
1523 ISOLATE_FLAG_LIST(INIT_FROM_FIELD)
1524#undef INIT_FROM_FIELD
1525 api_flags->entry_points = NULL;
1526 api_flags->load_vmservice_library = should_load_vmservice();
1527 api_flags->copy_parent_code = false;
1528 api_flags->null_safety = null_safety();
1529}
1530
1531void Isolate::FlagsCopyFrom(const Dart_IsolateFlags& api_flags) {
1532#if defined(DART_PRECOMPILER)
1533#define FLAG_FOR_PRECOMPILER(action) action
1534#else
1535#define FLAG_FOR_PRECOMPILER(action)
1536#endif
1537
1538#if !defined(PRODUCT)
1539#define FLAG_FOR_NONPRODUCT(action) action
1540#else
1541#define FLAG_FOR_NONPRODUCT(action)
1542#endif
1543
1544#define FLAG_FOR_PRODUCT(action) action
1545
1546#define SET_FROM_FLAG(when, name, bitname, isolate_flag, flag) \
1547 FLAG_FOR_##when(isolate_flags_ = bitname##Bit::update( \
1548 api_flags.isolate_flag, isolate_flags_));
1549
1550 ISOLATE_FLAG_LIST(SET_FROM_FLAG)
1551
1552#undef FLAG_FOR_NONPRODUCT
1553#undef FLAG_FOR_PRECOMPILER
1554#undef FLAG_FOR_PRODUCT
1555#undef SET_FROM_FLAG
1556
1557 set_should_load_vmservice(api_flags.load_vmservice_library);
1558 set_null_safety(api_flags.null_safety);
1559
1560 // Copy entry points list.
1561 ASSERT(embedder_entry_points_ == NULL);
1562 if (api_flags.entry_points != NULL) {
1563 intptr_t count = 0;
1564 while (api_flags.entry_points[count].function_name != NULL)
1565 count++;
1566 embedder_entry_points_ = new Dart_QualifiedFunctionName[count + 1];
1567 for (intptr_t i = 0; i < count; i++) {
1568 embedder_entry_points_[i].library_uri =
1569 Utils::StrDup(api_flags.entry_points[i].library_uri);
1570 embedder_entry_points_[i].class_name =
1571 Utils::StrDup(api_flags.entry_points[i].class_name);
1572 embedder_entry_points_[i].function_name =
1573 Utils::StrDup(api_flags.entry_points[i].function_name);
1574 }
1575 memset(&embedder_entry_points_[count], 0,
1576 sizeof(Dart_QualifiedFunctionName));
1577 }
1578
1579 // Leave others at defaults.
1580}
1581
1582#if defined(DEBUG)
1583// static
1584void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
1585 ASSERT(isolate == Isolate::Current());
1586}
1587
1588void BaseIsolate::AssertCurrentThreadIsMutator() const {
1589 ASSERT(Isolate::Current() == this);
1590 ASSERT(Thread::Current()->IsMutatorThread());
1591}
1592#endif // defined(DEBUG)
1593
1594#if defined(DEBUG)
1595#define REUSABLE_HANDLE_SCOPE_INIT(object) \
1596 reusable_##object##_handle_scope_active_(false),
1597#else
1598#define REUSABLE_HANDLE_SCOPE_INIT(object)
1599#endif // defined(DEBUG)
1600
1601#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(nullptr),
1602
1603// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
1604// that shared monitor.
1605Isolate::Isolate(IsolateGroup* isolate_group,
1606 const Dart_IsolateFlags& api_flags)
1607 : BaseIsolate(),
1608 current_tag_(UserTag::null()),
1609 default_tag_(UserTag::null()),
1610 ic_miss_code_(Code::null()),
1611 shared_class_table_(isolate_group->shared_class_table()),
1612 field_table_(new FieldTable()),
1613 isolate_group_(isolate_group),
1614 isolate_object_store_(
1615 new IsolateObjectStore(isolate_group->object_store())),
1616 object_store_shared_ptr_(isolate_group->object_store_shared_ptr()),
1617#if defined(DART_PRECOMPILED_RUNTIME)
1618 class_table_(isolate_group->class_table_shared_ptr()),
1619#else
1620 class_table_(new ClassTable(shared_class_table_)),
1621#endif
1622#if !defined(DART_PRECOMPILED_RUNTIME)
1623 native_callback_trampolines_(),
1624#endif
1625#if !defined(PRODUCT)
1626 last_resume_timestamp_(OS::GetCurrentTimeMillis()),
1627 vm_tag_counters_(),
1628 pending_service_extension_calls_(GrowableObjectArray::null()),
1629 registered_service_extension_handlers_(GrowableObjectArray::null()),
1630#define ISOLATE_METRIC_CONSTRUCTORS(type, variable, name, unit) \
1631 metric_##variable##_(),
1632 ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS)
1633#undef ISOLATE_METRIC_CONSTRUCTORS
1634 reload_every_n_stack_overflow_checks_(FLAG_reload_every),
1635#endif // !defined(PRODUCT)
1636 start_time_micros_(OS::GetCurrentMonotonicMicros()),
1637 random_(),
1638 mutex_(NOT_IN_PRODUCT("Isolate::mutex_")),
1639 constant_canonicalization_mutex_(
1640 NOT_IN_PRODUCT("Isolate::constant_canonicalization_mutex_")),
1641 megamorphic_mutex_(NOT_IN_PRODUCT("Isolate::megamorphic_mutex_")),
1642 kernel_data_lib_cache_mutex_(
1643 NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_")),
1644 kernel_data_class_cache_mutex_(
1645 NOT_IN_PRODUCT("Isolate::kernel_data_class_cache_mutex_")),
1646 kernel_constants_mutex_(
1647 NOT_IN_PRODUCT("Isolate::kernel_constants_mutex_")),
1648 pending_deopts_(new MallocGrowableArray<PendingLazyDeopt>()),
1649 tag_table_(GrowableObjectArray::null()),
1650 deoptimized_code_array_(GrowableObjectArray::null()),
1651 sticky_error_(Error::null()),
1652 field_list_mutex_(NOT_IN_PRODUCT("Isolate::field_list_mutex_")),
1653 boxed_field_list_(GrowableObjectArray::null()),
1654 spawn_count_monitor_(),
1655 handler_info_cache_(),
1656 catch_entry_moves_cache_() {
1657 cached_object_store_ = object_store_shared_ptr_.get();
1658 cached_class_table_table_ = class_table_->table();
1659 FlagsCopyFrom(api_flags);
1660 SetErrorsFatal(true);
1661 // TODO(asiva): A Thread is not available here, need to figure out
1662 // how the vm_tag (kEmbedderTagId) can be set, these tags need to
1663 // move to the OSThread structure.
1664 set_user_tag(UserTags::kDefaultUserTag);
1665
1666 if (obfuscate()) {
1667 OS::PrintErr(
1668 "Warning: This VM has been configured to obfuscate symbol information "
1669 "which violates the Dart standard.\n"
1670 " See dartbug.com/30524 for more information.\n");
1671 }
1672
1673 if (FLAG_enable_interpreter) {
1674 NOT_IN_PRECOMPILED(background_compiler_ = new BackgroundCompiler(
1675 this, /* optimizing = */ false));
1676 }
1677 NOT_IN_PRECOMPILED(optimizing_background_compiler_ =
1678 new BackgroundCompiler(this, /* optimizing = */ true));
1679}
1680
1681#undef REUSABLE_HANDLE_SCOPE_INIT
1682#undef REUSABLE_HANDLE_INITIALIZERS
1683
1684Isolate::~Isolate() {
1685#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
1686 // TODO(32796): Re-enable assertion.
1687 // RELEASE_ASSERT(reload_context_ == NULL);
1688#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
1689
1690 if (FLAG_enable_interpreter) {
1691 delete background_compiler_;
1692 background_compiler_ = nullptr;
1693 }
1694
1695 delete optimizing_background_compiler_;
1696 optimizing_background_compiler_ = nullptr;
1697
1698#if !defined(PRODUCT)
1699 delete debugger_;
1700 debugger_ = nullptr;
1701 delete object_id_ring_;
1702 object_id_ring_ = nullptr;
1703 delete pause_loop_monitor_;
1704 pause_loop_monitor_ = nullptr;
1705#endif // !defined(PRODUCT)
1706
1707 free(name_);
1708 delete field_table_;
1709#if defined(USING_SIMULATOR)
1710 delete simulator_;
1711#endif
1712 delete pending_deopts_;
1713 pending_deopts_ = nullptr;
1714 delete message_handler_;
1715 message_handler_ =
1716 nullptr; // Fail fast if we send messages to a dead isolate.
1717 ASSERT(deopt_context_ ==
1718 nullptr); // No deopt in progress when isolate deleted.
1719 ASSERT(spawn_count_ == 0);
1720
1721 // We have cached the mutator thread, delete it.
1722 ASSERT(scheduled_mutator_thread_ == nullptr);
1723 mutator_thread_->isolate_ = nullptr;
1724 delete mutator_thread_;
1725 mutator_thread_ = nullptr;
1726
1727 if (obfuscation_map_ != nullptr) {
1728 for (intptr_t i = 0; obfuscation_map_[i] != nullptr; i++) {
1729 delete[] obfuscation_map_[i];
1730 }
1731 delete[] obfuscation_map_;
1732 }
1733
1734 if (embedder_entry_points_ != nullptr) {
1735 for (intptr_t i = 0; embedder_entry_points_[i].function_name != nullptr;
1736 i++) {
1737 free(const_cast<char*>(embedder_entry_points_[i].library_uri));
1738 free(const_cast<char*>(embedder_entry_points_[i].class_name));
1739 free(const_cast<char*>(embedder_entry_points_[i].function_name));
1740 }
1741 delete[] embedder_entry_points_;
1742 }
1743}
1744
1745void Isolate::InitVM() {
1746 create_group_callback_ = nullptr;
1747 initialize_callback_ = nullptr;
1748 shutdown_callback_ = nullptr;
1749 cleanup_callback_ = nullptr;
1750 cleanup_group_callback_ = nullptr;
1751 if (isolate_creation_monitor_ == nullptr) {
1752 isolate_creation_monitor_ = new Monitor();
1753 }
1754 ASSERT(isolate_creation_monitor_ != nullptr);
1755 EnableIsolateCreation();
1756}
1757
1758Isolate* Isolate::InitIsolate(const char* name_prefix,
1759 IsolateGroup* isolate_group,
1760 const Dart_IsolateFlags& api_flags,
1761 bool is_vm_isolate) {
1762 Isolate* result = new Isolate(isolate_group, api_flags);
1763 result->BuildName(name_prefix);
1764 if (!is_vm_isolate) {
1765 // vm isolate object store is initialized later, after null instance
1766 // is created (in Dart::Init).
1767 // Non-vm isolates need to have isolate object store initialized is that
1768 // exit_listeners have to be null-initialized as they will be used if
1769 // we fail to create isolate below, have to do low level shutdown.
1770 if (result->object_store() == nullptr) {
1771 // in JIT with --enable-isolate-groups each isolate still
1772 // has to have its own object store
1773 result->set_object_store(new ObjectStore());
1774 result->object_store()->InitStubs();
1775 }
1776 result->isolate_object_store()->Init();
1777 }
1778
1779 ASSERT(result != nullptr);
1780
1781#if !defined(PRODUCT)
1782// Initialize metrics.
1783#define ISOLATE_METRIC_INIT(type, variable, name, unit) \
1784 result->metric_##variable##_.InitInstance(result, name, NULL, Metric::unit);
1785 ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT);
1786#undef ISOLATE_METRIC_INIT
1787#endif // !defined(PRODUCT)
1788
1789 // First we ensure we enter the isolate. This will ensure we're participating
1790 // in any safepointing requests from this point on. Other threads requesting a
1791 // safepoint operation will therefore wait until we've stopped.
1792 //
1793 // Though the [result] isolate is still in a state where no memory has been
1794 // allocated, which means it's safe to GC the isolate group until here.
1795 if (!Thread::EnterIsolate(result)) {
1796 delete result;
1797 return nullptr;
1798 }
1799
1800 // Setup the isolate message handler.
1801 MessageHandler* handler = new IsolateMessageHandler(result);
1802 ASSERT(handler != nullptr);
1803 result->set_message_handler(handler);
1804
1805 result->set_main_port(PortMap::CreatePort(result->message_handler()));
1806#if defined(DEBUG)
1807 // Verify that we are never reusing a live origin id.
1808 VerifyOriginId id_verifier(result->main_port());
1809 Isolate::VisitIsolates(&id_verifier);
1810#endif
1811 result->set_origin_id(result->main_port());
1812 result->set_pause_capability(result->random()->NextUInt64());
1813 result->set_terminate_capability(result->random()->NextUInt64());
1814
1815 // Now we register the isolate in the group. From this point on any GC would
1816 // traverse the isolate roots (before this point, the roots are only pointing
1817 // to vm-isolate objects, e.g. null)
1818 isolate_group->RegisterIsolate(result);
1819
1820 if (ServiceIsolate::NameEquals(name_prefix)) {
1821 ASSERT(!ServiceIsolate::Exists());
1822 ServiceIsolate::SetServiceIsolate(result);
1823#if !defined(DART_PRECOMPILED_RUNTIME)
1824 } else if (KernelIsolate::NameEquals(name_prefix)) {
1825 ASSERT(!KernelIsolate::Exists());
1826 KernelIsolate::SetKernelIsolate(result);
1827#endif // !defined(DART_PRECOMPILED_RUNTIME)
1828 }
1829
1830#if !defined(PRODUCT)
1831 result->debugger_ = new Debugger(result);
1832#endif
1833 if (FLAG_trace_isolates) {
1834 if (name_prefix == nullptr || strcmp(name_prefix, "vm-isolate") != 0) {
1835 OS::PrintErr(
1836 "[+] Starting isolate:\n"
1837 "\tisolate: %s\n",
1838 result->name());
1839 }
1840 }
1841
1842 // Add to isolate list. Shutdown and delete the isolate on failure.
1843 if (!TryMarkIsolateReady(result)) {
1844 result->LowLevelShutdown();
1845 Isolate::LowLevelCleanup(result);
1846 return nullptr;
1847 }
1848
1849 return result;
1850}
1851
1852Thread* Isolate::mutator_thread() const {
1853 ASSERT(thread_registry() != nullptr);
1854 return mutator_thread_;
1855}
1856
1857ObjectPtr Isolate::CallTagHandler(Dart_LibraryTag tag,
1858 const Object& arg1,
1859 const Object& arg2) {
1860 Thread* thread = Thread::Current();
1861 Api::Scope api_scope(thread);
1862 Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.raw());
1863 Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.raw());
1864 Dart_Handle api_result;
1865 {
1866 TransitionVMToNative transition(thread);
1867 ASSERT(HasTagHandler());
1868 api_result = group()->library_tag_handler()(tag, api_arg1, api_arg2);
1869 }
1870 return Api::UnwrapHandle(api_result);
1871}
1872
1873ObjectPtr Isolate::CallDeferredLoadHandler(intptr_t id) {
1874 Thread* thread = Thread::Current();
1875 Api::Scope api_scope(thread);
1876 Dart_Handle api_result;
1877 {
1878 TransitionVMToNative transition(thread);
1879 RELEASE_ASSERT(HasDeferredLoadHandler());
1880 api_result = group()->deferred_load_handler()(id);
1881 }
1882 return Api::UnwrapHandle(api_result);
1883}
1884
1885void Isolate::SetupImagePage(const uint8_t* image_buffer, bool is_executable) {
1886 Image image(image_buffer);
1887 heap()->SetupImagePage(image.object_start(), image.object_size(),
1888 is_executable);
1889}
1890
1891void Isolate::ScheduleInterrupts(uword interrupt_bits) {
1892 // We take the threads lock here to ensure that the mutator thread does not
1893 // exit the isolate while we are trying to schedule interrupts on it.
1894 MonitorLocker ml(group()->threads_lock());
1895 Thread* mthread = mutator_thread();
1896 if (mthread != nullptr) {
1897 mthread->ScheduleInterrupts(interrupt_bits);
1898 }
1899}
1900
1901void Isolate::set_name(const char* name) {
1902 free(name_);
1903 name_ = Utils::StrDup(name);
1904}
1905
1906int64_t IsolateGroup::UptimeMicros() const {
1907 return OS::GetCurrentMonotonicMicros() - start_time_micros_;
1908}
1909
1910int64_t Isolate::UptimeMicros() const {
1911 return OS::GetCurrentMonotonicMicros() - start_time_micros_;
1912}
1913
1914Dart_Port Isolate::origin_id() {
1915 MutexLocker ml(&origin_id_mutex_);
1916 return origin_id_;
1917}
1918
1919void Isolate::set_origin_id(Dart_Port id) {
1920 MutexLocker ml(&origin_id_mutex_);
1921 ASSERT((id == main_port_ && origin_id_ == 0) || (origin_id_ == main_port_));
1922 origin_id_ = id;
1923}
1924
1925bool Isolate::IsPaused() const {
1926#if defined(PRODUCT)
1927 return false;
1928#else
1929 return (debugger_ != nullptr) && (debugger_->PauseEvent() != nullptr);
1930#endif // !defined(PRODUCT)
1931}
1932
1933ErrorPtr Isolate::PausePostRequest() {
1934#if !defined(PRODUCT)
1935 if (debugger_ == nullptr) {
1936 return Error::null();
1937 }
1938 ASSERT(!IsPaused());
1939 const Error& error = Error::Handle(debugger_->PausePostRequest());
1940 if (!error.IsNull()) {
1941 if (Thread::Current()->top_exit_frame_info() == 0) {
1942 return error.raw();
1943 } else {
1944 Exceptions::PropagateError(error);
1945 UNREACHABLE();
1946 }
1947 }
1948#endif
1949 return Error::null();
1950}
1951
1952void Isolate::BuildName(const char* name_prefix) {
1953 ASSERT(name_ == nullptr);
1954 if (name_prefix == nullptr) {
1955 name_ = OS::SCreate(nullptr, "isolate-%" Pd64 "", main_port());
1956 } else {
1957 name_ = Utils::StrDup(name_prefix);
1958 }
1959}
1960
1961#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
1962bool Isolate::CanReload() const {
1963 return !Isolate::IsVMInternalIsolate(this) && is_runnable() &&
1964 !group()->IsReloading() && (no_reload_scope_depth_ == 0) &&
1965 IsolateCreationEnabled() &&
1966 OSThread::Current()->HasStackHeadroom(64 * KB);
1967}
1968
1969bool IsolateGroup::ReloadSources(JSONStream* js,
1970 bool force_reload,
1971 const char* root_script_url,
1972 const char* packages_url,
1973 bool dont_delete_reload_context) {
1974 ASSERT(!IsReloading());
1975
1976 // TODO(dartbug.com/36097): Support multiple isolates within an isolate group.
1977 RELEASE_ASSERT(!FLAG_enable_isolate_groups);
1978 RELEASE_ASSERT(isolates_.First() == isolates_.Last());
1979 RELEASE_ASSERT(isolates_.First() == Isolate::Current());
1980
1981 auto shared_class_table = IsolateGroup::Current()->shared_class_table();
1982 std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
1983 new IsolateGroupReloadContext(this, shared_class_table, js));
1984 group_reload_context_ = group_reload_context;
1985
1986 ForEachIsolate([&](Isolate* isolate) {
1987 isolate->SetHasAttemptedReload(true);
1988 isolate->reload_context_ =
1989 new IsolateReloadContext(group_reload_context_, isolate);
1990 });
1991 const bool success =
1992 group_reload_context_->Reload(force_reload, root_script_url, packages_url,
1993 /*kernel_buffer=*/nullptr,
1994 /*kernel_buffer_size=*/0);
1995 if (!dont_delete_reload_context) {
1996 ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
1997 DeleteReloadContext();
1998 }
1999 return success;
2000}
2001
2002bool IsolateGroup::ReloadKernel(JSONStream* js,
2003 bool force_reload,
2004 const uint8_t* kernel_buffer,
2005 intptr_t kernel_buffer_size,
2006 bool dont_delete_reload_context) {
2007 ASSERT(!IsReloading());
2008
2009 // TODO(dartbug.com/36097): Support multiple isolates within an isolate group.
2010 RELEASE_ASSERT(!FLAG_enable_isolate_groups);
2011 RELEASE_ASSERT(isolates_.First() == isolates_.Last());
2012 RELEASE_ASSERT(isolates_.First() == Isolate::Current());
2013
2014 auto shared_class_table = IsolateGroup::Current()->shared_class_table();
2015 std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
2016 new IsolateGroupReloadContext(this, shared_class_table, js));
2017 group_reload_context_ = group_reload_context;
2018
2019 ForEachIsolate([&](Isolate* isolate) {
2020 isolate->SetHasAttemptedReload(true);
2021 isolate->reload_context_ =
2022 new IsolateReloadContext(group_reload_context_, isolate);
2023 });
2024 const bool success = group_reload_context_->Reload(
2025 force_reload,
2026 /*root_script_url=*/nullptr,
2027 /*packages_url=*/nullptr, kernel_buffer, kernel_buffer_size);
2028 if (!dont_delete_reload_context) {
2029 ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
2030 DeleteReloadContext();
2031 }
2032 return success;
2033}
2034
2035void IsolateGroup::DeleteReloadContext() {
2036 SafepointOperationScope safepoint_scope(Thread::Current());
2037 group_reload_context_.reset();
2038}
2039
2040void Isolate::DeleteReloadContext() {
2041 // Another thread may be in the middle of GetClassForHeapWalkAt.
2042 SafepointOperationScope safepoint_scope(Thread::Current());
2043
2044 delete reload_context_;
2045 reload_context_ = nullptr;
2046}
2047#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2048
2049const char* Isolate::MakeRunnable() {
2050 ASSERT(Isolate::Current() == nullptr);
2051
2052 MutexLocker ml(&mutex_);
2053 // Check if we are in a valid state to make the isolate runnable.
2054 if (is_runnable() == true) {
2055 return "Isolate is already runnable";
2056 }
2057 // Set the isolate as runnable and if we are being spawned schedule
2058 // isolate on thread pool for execution.
2059 ASSERT(object_store()->root_library() != Library::null());
2060 set_is_runnable(true);
2061#ifndef PRODUCT
2062 if (!Isolate::IsVMInternalIsolate(this)) {
2063 debugger()->OnIsolateRunnable();
2064 if (FLAG_pause_isolates_on_unhandled_exceptions) {
2065 debugger()->SetExceptionPauseInfo(kPauseOnUnhandledExceptions);
2066 }
2067 }
2068#endif // !PRODUCT
2069 IsolateSpawnState* state = spawn_state();
2070 if (state != nullptr) {
2071 ASSERT(this == state->isolate());
2072 Run();
2073 }
2074#if defined(SUPPORT_TIMELINE)
2075 TimelineStream* stream = Timeline::GetIsolateStream();
2076 ASSERT(stream != nullptr);
2077 TimelineEvent* event = stream->StartEvent();
2078 if (event != nullptr) {
2079 event->Instant("Runnable");
2080 event->Complete();
2081 }
2082#endif
2083#ifndef PRODUCT
2084 if (!Isolate::IsVMInternalIsolate(this) &&
2085 Service::isolate_stream.enabled()) {
2086 ServiceEvent runnableEvent(this, ServiceEvent::kIsolateRunnable);
2087 Service::HandleEvent(&runnableEvent);
2088 }
2089 GetRunnableLatencyMetric()->set_value(UptimeMicros());
2090 if (FLAG_print_benchmarking_metrics) {
2091 {
2092 StartIsolateScope scope(this);
2093 heap()->CollectAllGarbage();
2094 }
2095 int64_t heap_size = (heap()->UsedInWords(Heap::kNew) * kWordSize) +
2096 (heap()->UsedInWords(Heap::kOld) * kWordSize);
2097 GetRunnableHeapSizeMetric()->set_value(heap_size);
2098 }
2099#endif // !PRODUCT
2100 return nullptr;
2101}
2102
2103bool Isolate::VerifyPauseCapability(const Object& capability) const {
2104 return !capability.IsNull() && capability.IsCapability() &&
2105 (pause_capability() == Capability::Cast(capability).Id());
2106}
2107
2108bool Isolate::VerifyTerminateCapability(const Object& capability) const {
2109 return !capability.IsNull() && capability.IsCapability() &&
2110 (terminate_capability() == Capability::Cast(capability).Id());
2111}
2112
2113bool Isolate::AddResumeCapability(const Capability& capability) {
2114 // Ensure a limit for the number of resume capabilities remembered.
2115 static const intptr_t kMaxResumeCapabilities =
2116 compiler::target::kSmiMax / (6 * kWordSize);
2117
2118 const GrowableObjectArray& caps = GrowableObjectArray::Handle(
2119 current_zone(), isolate_object_store()->resume_capabilities());
2120 Capability& current = Capability::Handle(current_zone());
2121 intptr_t insertion_index = -1;
2122 for (intptr_t i = 0; i < caps.Length(); i++) {
2123 current ^= caps.At(i);
2124 if (current.IsNull()) {
2125 if (insertion_index < 0) {
2126 insertion_index = i;
2127 }
2128 } else if (current.Id() == capability.Id()) {
2129 return false;
2130 }
2131 }
2132 if (insertion_index < 0) {
2133 if (caps.Length() >= kMaxResumeCapabilities) {
2134 // Cannot grow the array of resume capabilities beyond its max. Additional
2135 // pause requests are ignored. In practice will never happen as we will
2136 // run out of memory beforehand.
2137 return false;
2138 }
2139 caps.Add(capability);
2140 } else {
2141 caps.SetAt(insertion_index, capability);
2142 }
2143 return true;
2144}
2145
2146bool Isolate::RemoveResumeCapability(const Capability& capability) {
2147 const GrowableObjectArray& caps = GrowableObjectArray::Handle(
2148 current_zone(), isolate_object_store()->resume_capabilities());
2149 Capability& current = Capability::Handle(current_zone());
2150 for (intptr_t i = 0; i < caps.Length(); i++) {
2151 current ^= caps.At(i);
2152 if (!current.IsNull() && (current.Id() == capability.Id())) {
2153 // Remove the matching capability from the list.
2154 current = Capability::null();
2155 caps.SetAt(i, current);
2156 return true;
2157 }
2158 }
2159 return false;
2160}
2161
2162// TODO(iposva): Remove duplicated code and start using some hash based
2163// structure instead of these linear lookups.
2164void Isolate::AddExitListener(const SendPort& listener,
2165 const Instance& response) {
2166 // Ensure a limit for the number of listeners remembered.
2167 static const intptr_t kMaxListeners =
2168 compiler::target::kSmiMax / (12 * kWordSize);
2169
2170 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2171 current_zone(), isolate_object_store()->exit_listeners());
2172 SendPort& current = SendPort::Handle(current_zone());
2173 intptr_t insertion_index = -1;
2174 for (intptr_t i = 0; i < listeners.Length(); i += 2) {
2175 current ^= listeners.At(i);
2176 if (current.IsNull()) {
2177 if (insertion_index < 0) {
2178 insertion_index = i;
2179 }
2180 } else if (current.Id() == listener.Id()) {
2181 listeners.SetAt(i + 1, response);
2182 return;
2183 }
2184 }
2185 if (insertion_index < 0) {
2186 if (listeners.Length() >= kMaxListeners) {
2187 // Cannot grow the array of listeners beyond its max. Additional
2188 // listeners are ignored. In practice will never happen as we will
2189 // run out of memory beforehand.
2190 return;
2191 }
2192 listeners.Add(listener);
2193 listeners.Add(response);
2194 } else {
2195 listeners.SetAt(insertion_index, listener);
2196 listeners.SetAt(insertion_index + 1, response);
2197 }
2198}
2199
2200void Isolate::RemoveExitListener(const SendPort& listener) {
2201 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2202 current_zone(), isolate_object_store()->exit_listeners());
2203 SendPort& current = SendPort::Handle(current_zone());
2204 for (intptr_t i = 0; i < listeners.Length(); i += 2) {
2205 current ^= listeners.At(i);
2206 if (!current.IsNull() && (current.Id() == listener.Id())) {
2207 // Remove the matching listener from the list.
2208 current = SendPort::null();
2209 listeners.SetAt(i, current);
2210 listeners.SetAt(i + 1, Object::null_instance());
2211 return;
2212 }
2213 }
2214}
2215
2216void Isolate::NotifyExitListeners() {
2217 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2218 current_zone(), isolate_object_store()->exit_listeners());
2219 if (listeners.IsNull()) return;
2220
2221 SendPort& listener = SendPort::Handle(current_zone());
2222 Instance& response = Instance::Handle(current_zone());
2223 for (intptr_t i = 0; i < listeners.Length(); i += 2) {
2224 listener ^= listeners.At(i);
2225 if (!listener.IsNull()) {
2226 Dart_Port port_id = listener.Id();
2227 response ^= listeners.At(i + 1);
2228 PortMap::PostMessage(SerializeMessage(port_id, response));
2229 }
2230 }
2231}
2232
2233void Isolate::AddErrorListener(const SendPort& listener) {
2234 // Ensure a limit for the number of listeners remembered.
2235 static const intptr_t kMaxListeners =
2236 compiler::target::kSmiMax / (6 * kWordSize);
2237
2238 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2239 current_zone(), isolate_object_store()->error_listeners());
2240 SendPort& current = SendPort::Handle(current_zone());
2241 intptr_t insertion_index = -1;
2242 for (intptr_t i = 0; i < listeners.Length(); i++) {
2243 current ^= listeners.At(i);
2244 if (current.IsNull()) {
2245 if (insertion_index < 0) {
2246 insertion_index = i;
2247 }
2248 } else if (current.Id() == listener.Id()) {
2249 return;
2250 }
2251 }
2252 if (insertion_index < 0) {
2253 if (listeners.Length() >= kMaxListeners) {
2254 // Cannot grow the array of listeners beyond its max. Additional
2255 // listeners are ignored. In practice will never happen as we will
2256 // run out of memory beforehand.
2257 return;
2258 }
2259 listeners.Add(listener);
2260 } else {
2261 listeners.SetAt(insertion_index, listener);
2262 }
2263}
2264
2265void Isolate::RemoveErrorListener(const SendPort& listener) {
2266 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2267 current_zone(), isolate_object_store()->error_listeners());
2268 SendPort& current = SendPort::Handle(current_zone());
2269 for (intptr_t i = 0; i < listeners.Length(); i++) {
2270 current ^= listeners.At(i);
2271 if (!current.IsNull() && (current.Id() == listener.Id())) {
2272 // Remove the matching listener from the list.
2273 current = SendPort::null();
2274 listeners.SetAt(i, current);
2275 return;
2276 }
2277 }
2278}
2279
2280bool Isolate::NotifyErrorListeners(const String& msg,
2281 const String& stacktrace) {
2282 const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
2283 current_zone(), isolate_object_store()->error_listeners());
2284 if (listeners.IsNull()) return false;
2285
2286 const Array& arr = Array::Handle(current_zone(), Array::New(2));
2287 arr.SetAt(0, msg);
2288 arr.SetAt(1, stacktrace);
2289 SendPort& listener = SendPort::Handle(current_zone());
2290 for (intptr_t i = 0; i < listeners.Length(); i++) {
2291 listener ^= listeners.At(i);
2292 if (!listener.IsNull()) {
2293 Dart_Port port_id = listener.Id();
2294 PortMap::PostMessage(SerializeMessage(port_id, arr));
2295 }
2296 }
2297 return listeners.Length() > 0;
2298}
2299
2300static MessageHandler::MessageStatus RunIsolate(uword parameter) {
2301 Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
2302 IsolateSpawnState* state = nullptr;
2303 {
2304 // TODO(turnidge): Is this locking required here at all anymore?
2305 MutexLocker ml(isolate->mutex());
2306 state = isolate->spawn_state();
2307 }
2308 {
2309 StartIsolateScope start_scope(isolate);
2310 Thread* thread = Thread::Current();
2311 ASSERT(thread->isolate() == isolate);
2312 StackZone zone(thread);
2313 HandleScope handle_scope(thread);
2314
2315 // If particular values were requested for this newly spawned isolate, then
2316 // they are set here before the isolate starts executing user code.
2317 isolate->SetErrorsFatal(state->errors_are_fatal());
2318 if (state->on_exit_port() != ILLEGAL_PORT) {
2319 const SendPort& listener =
2320 SendPort::Handle(SendPort::New(state->on_exit_port()));
2321 isolate->AddExitListener(listener, Instance::null_instance());
2322 }
2323 if (state->on_error_port() != ILLEGAL_PORT) {
2324 const SendPort& listener =
2325 SendPort::Handle(SendPort::New(state->on_error_port()));
2326 isolate->AddErrorListener(listener);
2327 }
2328
2329 // Switch back to spawning isolate.
2330
2331 if (!ClassFinalizer::ProcessPendingClasses()) {
2332// Error is in sticky error already.
2333#if defined(DEBUG)
2334 const Error& error = Error::Handle(thread->sticky_error());
2335 ASSERT(!error.IsUnwindError());
2336#endif
2337 return MessageHandler::kError;
2338 }
2339
2340 Object& result = Object::Handle();
2341 result = state->ResolveFunction();
2342 bool is_spawn_uri = state->is_spawn_uri();
2343 if (result.IsError()) {
2344 return StoreError(thread, Error::Cast(result));
2345 }
2346 ASSERT(result.IsFunction());
2347 Function& func = Function::Handle(thread->zone());
2348 func ^= result.raw();
2349
2350 func = func.ImplicitClosureFunction();
2351
2352 const Array& capabilities = Array::Handle(Array::New(2));
2353 Capability& capability = Capability::Handle();
2354 capability = Capability::New(isolate->pause_capability());
2355 capabilities.SetAt(0, capability);
2356 // Check whether this isolate should be started in paused state.
2357 if (state->paused()) {
2358 bool added = isolate->AddResumeCapability(capability);
2359 ASSERT(added); // There should be no pending resume capabilities.
2360 isolate->message_handler()->increment_paused();
2361 }
2362 capability = Capability::New(isolate->terminate_capability());
2363 capabilities.SetAt(1, capability);
2364
2365 // Instead of directly invoking the entry point we call '_startIsolate' with
2366 // the entry point as argument.
2367 // Since this function ("RunIsolate") is used for both Isolate.spawn and
2368 // Isolate.spawnUri we also send a boolean flag as argument so that the
2369 // "_startIsolate" function can act corresponding to how the isolate was
2370 // created.
2371 const Array& args = Array::Handle(Array::New(7));
2372 args.SetAt(0, SendPort::Handle(SendPort::New(state->parent_port())));
2373 args.SetAt(1, Instance::Handle(func.ImplicitStaticClosure()));
2374 args.SetAt(2, Instance::Handle(state->BuildArgs(thread)));
2375 args.SetAt(3, Instance::Handle(state->BuildMessage(thread)));
2376 args.SetAt(4, is_spawn_uri ? Bool::True() : Bool::False());
2377 args.SetAt(5, ReceivePort::Handle(ReceivePort::New(
2378 isolate->main_port(), true /* control port */)));
2379 args.SetAt(6, capabilities);
2380
2381 const Library& lib = Library::Handle(Library::IsolateLibrary());
2382 const String& entry_name = String::Handle(String::New("_startIsolate"));
2383 const Function& entry_point =
2384 Function::Handle(lib.LookupLocalFunction(entry_name));
2385 ASSERT(entry_point.IsFunction() && !entry_point.IsNull());
2386
2387 result = DartEntry::InvokeFunction(entry_point, args);
2388 if (result.IsError()) {
2389 return StoreError(thread, Error::Cast(result));
2390 }
2391 }
2392 return MessageHandler::kOK;
2393}
2394
2395static void ShutdownIsolate(uword parameter) {
2396 Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
2397 {
2398 // Print the error if there is one. This may execute dart code to
2399 // print the exception object, so we need to use a StartIsolateScope.
2400 StartIsolateScope start_scope(isolate);
2401 Thread* thread = Thread::Current();
2402 ASSERT(thread->isolate() == isolate);
2403
2404 // We must wait for any outstanding spawn calls to complete before
2405 // running the shutdown callback.
2406 isolate->WaitForOutstandingSpawns();
2407
2408 StackZone zone(thread);
2409 HandleScope handle_scope(thread);
2410#if defined(DEBUG)
2411 isolate->ValidateConstants();
2412#endif // defined(DEBUG)
2413 Dart::RunShutdownCallback();
2414 }
2415 // Shut the isolate down.
2416 Dart::ShutdownIsolate(isolate);
2417}
2418
2419void Isolate::SetStickyError(ErrorPtr sticky_error) {
2420 ASSERT(
2421 ((sticky_error_ == Error::null()) || (sticky_error == Error::null())) &&
2422 (sticky_error != sticky_error_));
2423 sticky_error_ = sticky_error;
2424}
2425
2426void Isolate::Run() {
2427 message_handler()->Run(group()->thread_pool(), RunIsolate, ShutdownIsolate,
2428 reinterpret_cast<uword>(this));
2429}
2430
2431void Isolate::AddClosureFunction(const Function& function) const {
2432 ASSERT(!Compiler::IsBackgroundCompilation());
2433 GrowableObjectArray& closures =
2434 GrowableObjectArray::Handle(object_store()->closure_functions());
2435 ASSERT(!closures.IsNull());
2436 ASSERT(function.IsNonImplicitClosureFunction());
2437 closures.Add(function, Heap::kOld);
2438}
2439
2440// If the linear lookup turns out to be too expensive, the list
2441// of closures could be maintained in a hash map, with the key
2442// being the token position of the closure. There are almost no
2443// collisions with this simple hash value. However, iterating over
2444// all closure functions becomes more difficult, especially when
2445// the list/map changes while iterating over it.
2446FunctionPtr Isolate::LookupClosureFunction(const Function& parent,
2447 TokenPosition token_pos) const {
2448 const GrowableObjectArray& closures =
2449 GrowableObjectArray::Handle(object_store()->closure_functions());
2450 ASSERT(!closures.IsNull());
2451 Function& closure = Function::Handle();
2452 intptr_t num_closures = closures.Length();
2453 for (intptr_t i = 0; i < num_closures; i++) {
2454 closure ^= closures.At(i);
2455 if ((closure.token_pos() == token_pos) &&
2456 (closure.parent_function() == parent.raw())) {
2457 return closure.raw();
2458 }
2459 }
2460 return Function::null();
2461}
2462
2463intptr_t Isolate::FindClosureIndex(const Function& needle) const {
2464 const GrowableObjectArray& closures_array =
2465 GrowableObjectArray::Handle(object_store()->closure_functions());
2466 intptr_t num_closures = closures_array.Length();
2467 for (intptr_t i = 0; i < num_closures; i++) {
2468 if (closures_array.At(i) == needle.raw()) {
2469 return i;
2470 }
2471 }
2472 return -1;
2473}
2474
2475FunctionPtr Isolate::ClosureFunctionFromIndex(intptr_t idx) const {
2476 const GrowableObjectArray& closures_array =
2477 GrowableObjectArray::Handle(object_store()->closure_functions());
2478 if ((idx < 0) || (idx >= closures_array.Length())) {
2479 return Function::null();
2480 }
2481 return Function::RawCast(closures_array.At(idx));
2482}
2483
2484// static
2485void Isolate::NotifyLowMemory() {
2486 Isolate::KillAllIsolates(Isolate::kLowMemoryMsg);
2487}
2488
2489void Isolate::LowLevelShutdown() {
2490 // Ensure we have a zone and handle scope so that we can call VM functions,
2491 // but we no longer allocate new heap objects.
2492 Thread* thread = Thread::Current();
2493 StackZone stack_zone(thread);
2494 HandleScope handle_scope(thread);
2495 NoSafepointScope no_safepoint_scope;
2496
2497 // Notify exit listeners that this isolate is shutting down.
2498 if (object_store() != nullptr) {
2499 const Error& error = Error::Handle(thread->sticky_error());
2500 if (error.IsNull() || !error.IsUnwindError() ||
2501 UnwindError::Cast(error).is_user_initiated()) {
2502 NotifyExitListeners();
2503 }
2504 }
2505
2506 // Close all the ports owned by this isolate.
2507 PortMap::ClosePorts(message_handler());
2508
2509 // Fail fast if anybody tries to post any more messages to this isolate.
2510 delete message_handler();
2511 set_message_handler(nullptr);
2512#if defined(SUPPORT_TIMELINE)
2513 // Before analyzing the isolate's timeline blocks- reclaim all cached
2514 // blocks.
2515 Timeline::ReclaimCachedBlocksFromThreads();
2516#endif
2517
2518// Dump all timing data for the isolate.
2519#if defined(SUPPORT_TIMELINE) && !defined(PRODUCT)
2520 if (FLAG_timing) {
2521 TimelinePauseTrace tpt;
2522 tpt.Print();
2523 }
2524#endif // !PRODUCT
2525
2526#if !defined(PRODUCT)
2527 if (FLAG_dump_megamorphic_stats) {
2528 MegamorphicCacheTable::PrintSizes(this);
2529 }
2530 if (FLAG_dump_symbol_stats) {
2531 Symbols::DumpStats(this);
2532 }
2533 if (FLAG_trace_isolates) {
2534 heap()->PrintSizes();
2535 OS::PrintErr(
2536 "[-] Stopping isolate:\n"
2537 "\tisolate: %s\n",
2538 name());
2539 }
2540 if (FLAG_print_metrics || FLAG_print_benchmarking_metrics) {
2541 LogBlock lb;
2542 OS::PrintErr("Printing metrics for %s\n", name());
2543#define ISOLATE_GROUP_METRIC_PRINT(type, variable, name, unit) \
2544 OS::PrintErr("%s\n", isolate_group_->Get##variable##Metric()->ToString());
2545 ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_PRINT)
2546#undef ISOLATE_GROUP_METRIC_PRINT
2547#define ISOLATE_METRIC_PRINT(type, variable, name, unit) \
2548 OS::PrintErr("%s\n", metric_##variable##_.ToString());
2549 ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT)
2550#undef ISOLATE_METRIC_PRINT
2551 OS::PrintErr("\n");
2552 }
2553#endif // !defined(PRODUCT)
2554}
2555
2556#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2557void Isolate::MaybeIncreaseReloadEveryNStackOverflowChecks() {
2558 if (FLAG_reload_every_back_off) {
2559 if (reload_every_n_stack_overflow_checks_ < 5000) {
2560 reload_every_n_stack_overflow_checks_ += 99;
2561 } else {
2562 reload_every_n_stack_overflow_checks_ *= 2;
2563 }
2564 // Cap the value.
2565 if (reload_every_n_stack_overflow_checks_ > 1000000) {
2566 reload_every_n_stack_overflow_checks_ = 1000000;
2567 }
2568 }
2569}
2570#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2571
2572void Isolate::set_forward_table_new(WeakTable* table) {
2573 std::unique_ptr<WeakTable> value(table);
2574 forward_table_new_ = std::move(value);
2575}
2576void Isolate::set_forward_table_old(WeakTable* table) {
2577 std::unique_ptr<WeakTable> value(table);
2578 forward_table_old_ = std::move(value);
2579}
2580
2581void Isolate::Shutdown() {
2582 ASSERT(this == Isolate::Current());
2583 BackgroundCompiler::Stop(this);
2584 if (FLAG_enable_interpreter) {
2585 delete background_compiler_;
2586 background_compiler_ = nullptr;
2587 }
2588 delete optimizing_background_compiler_;
2589 optimizing_background_compiler_ = nullptr;
2590
2591 Thread* thread = Thread::Current();
2592
2593 // Don't allow anymore dart code to execution on this isolate.
2594 thread->ClearStackLimit();
2595
2596 {
2597 StackZone zone(thread);
2598 HandleScope handle_scope(thread);
2599 ServiceIsolate::SendIsolateShutdownMessage();
2600 KernelIsolate::NotifyAboutIsolateShutdown(this);
2601#if !defined(PRODUCT)
2602 debugger()->Shutdown();
2603#endif
2604 }
2605
2606#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2607 if (FLAG_check_reloaded && is_runnable() &&
2608 !Isolate::IsVMInternalIsolate(this)) {
2609 if (!HasAttemptedReload()) {
2610 FATAL(
2611 "Isolate did not reload before exiting and "
2612 "--check-reloaded is enabled.\n");
2613 }
2614 }
2615
2616#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2617
2618 // Then, proceed with low-level teardown.
2619 Isolate::UnMarkIsolateReady(this);
2620
2621 // Post message before LowLevelShutdown that sends onExit message.
2622 // This ensures that exit message comes last.
2623 if (bequest_.get() != nullptr) {
2624 auto beneficiary = bequest_->beneficiary();
2625 PortMap::PostMessage(Message::New(beneficiary, bequest_.release(),
2626 Message::kNormalPriority));
2627 }
2628
2629 LowLevelShutdown();
2630
2631 // Now we can unregister from the thread, invoke cleanup callback, delete the
2632 // isolate (and possibly the isolate group).
2633 Isolate::LowLevelCleanup(this);
2634}
2635
2636void Isolate::LowLevelCleanup(Isolate* isolate) {
2637#if !defined(DART_PECOMPILED_RUNTIME)
2638 if (KernelIsolate::IsKernelIsolate(isolate)) {
2639 KernelIsolate::SetKernelIsolate(nullptr);
2640#endif
2641 } else if (ServiceIsolate::IsServiceIsolate(isolate)) {
2642 ServiceIsolate::SetServiceIsolate(nullptr);
2643 }
2644
2645 // Cache these two fields, since they are no longer available after the
2646 // `delete this` further down.
2647 IsolateGroup* isolate_group = isolate->isolate_group_;
2648 Dart_IsolateCleanupCallback cleanup = Isolate::CleanupCallback();
2649 auto callback_data = isolate->init_callback_data_;
2650
2651 // From this point on the isolate is no longer visited by GC (which is ok,
2652 // since we're just going to delete it anyway).
2653 isolate_group->UnregisterIsolate(isolate);
2654
2655 // From this point on the isolate doesn't participate in safepointing
2656 // requests anymore.
2657 Thread::ExitIsolate();
2658
2659 // Now it's safe to delete the isolate.
2660 delete isolate;
2661
2662 // Run isolate specific cleanup function for all non "vm-isolate's.
2663 const bool is_vm_isolate = Dart::vm_isolate() == isolate;
2664 if (!is_vm_isolate) {
2665 if (cleanup != nullptr) {
2666 cleanup(isolate_group->embedder_data(), callback_data);
2667 }
2668 }
2669
2670 const bool shutdown_group =
2671 isolate_group->UnregisterIsolateDecrementCount(isolate);
2672 if (shutdown_group) {
2673 // The "vm-isolate" does not have a thread pool.
2674 ASSERT(is_vm_isolate == (isolate_group->thread_pool() == nullptr));
2675 if (is_vm_isolate ||
2676 !isolate_group->thread_pool()->CurrentThreadIsWorker()) {
2677 isolate_group->Shutdown();
2678 } else {
2679 class ShutdownGroupTask : public ThreadPool::Task {
2680 public:
2681 explicit ShutdownGroupTask(IsolateGroup* isolate_group)
2682 : isolate_group_(isolate_group) {}
2683
2684 virtual void Run() { isolate_group_->Shutdown(); }
2685
2686 private:
2687 IsolateGroup* isolate_group_;
2688 };
2689 // The current thread is running on the isolate group's thread pool.
2690 // So we cannot safely delete the isolate group (and it's pool).
2691 // Instead we will destroy the isolate group on the VM-global pool.
2692 Dart::thread_pool()->Run<ShutdownGroupTask>(isolate_group);
2693 }
2694 } else {
2695 if (FLAG_enable_isolate_groups) {
2696 // TODO(dartbug.com/36097): An isolate just died. A significant amount of
2697 // memory might have become unreachable. We should evaluate how to best
2698 // inform the GC about this situation.
2699 }
2700 }
2701} // namespace dart
2702
2703Dart_InitializeIsolateCallback Isolate::initialize_callback_ = nullptr;
2704Dart_IsolateGroupCreateCallback Isolate::create_group_callback_ = nullptr;
2705Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = nullptr;
2706Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = nullptr;
2707Dart_IsolateGroupCleanupCallback Isolate::cleanup_group_callback_ = nullptr;
2708
2709Random* IsolateGroup::isolate_group_random_ = nullptr;
2710Monitor* Isolate::isolate_creation_monitor_ = nullptr;
2711bool Isolate::creation_enabled_ = false;
2712
2713RwLock* IsolateGroup::isolate_groups_rwlock_ = nullptr;
2714IntrusiveDList<IsolateGroup>* IsolateGroup::isolate_groups_ = nullptr;
2715
2716void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
2717 ValidationPolicy validate_frames) {
2718 ASSERT(visitor != nullptr);
2719
2720 // Visit objects in the object store if there is no isolate group object store
2721 if (group()->object_store() == nullptr && object_store() != nullptr) {
2722 object_store()->VisitObjectPointers(visitor);
2723 }
2724 // Visit objects in the isolate object store.
2725 if (isolate_object_store() != nullptr) {
2726 isolate_object_store()->VisitObjectPointers(visitor);
2727 }
2728
2729 // Visit objects in the class table unless it's shared by the group.
2730 // If it is shared, it is visited by IsolateGroup::VisitObjectPointers
2731 if (group()->class_table() != class_table()) {
2732 class_table()->VisitObjectPointers(visitor);
2733 }
2734
2735 // Visit objects in the field table.
2736 field_table()->VisitObjectPointers(visitor);
2737
2738 visitor->clear_gc_root_type();
2739 // Visit the objects directly referenced from the isolate structure.
2740 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&current_tag_));
2741 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&default_tag_));
2742 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&ic_miss_code_));
2743 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&tag_table_));
2744 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&deoptimized_code_array_));
2745 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&sticky_error_));
2746 if (isolate_group_ != nullptr) {
2747 if (isolate_group_->source()->loaded_blobs_ != nullptr) {
2748 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(
2749 &(isolate_group_->source()->loaded_blobs_)));
2750 }
2751 }
2752#if !defined(PRODUCT)
2753 visitor->VisitPointer(
2754 reinterpret_cast<ObjectPtr*>(&pending_service_extension_calls_));
2755 visitor->VisitPointer(
2756 reinterpret_cast<ObjectPtr*>(&registered_service_extension_handlers_));
2757#endif // !defined(PRODUCT)
2758 // Visit the boxed_field_list_.
2759 // 'boxed_field_list_' access via mutator and background compilation threads
2760 // is guarded with a monitor. This means that we can visit it only
2761 // when at safepoint or the field_list_mutex_ lock has been taken.
2762 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&boxed_field_list_));
2763
2764 if (background_compiler() != nullptr) {
2765 background_compiler()->VisitPointers(visitor);
2766 }
2767 if (optimizing_background_compiler() != nullptr) {
2768 optimizing_background_compiler()->VisitPointers(visitor);
2769 }
2770
2771#if !defined(PRODUCT)
2772 // Visit objects in the debugger.
2773 if (debugger() != nullptr) {
2774 debugger()->VisitObjectPointers(visitor);
2775 }
2776#if !defined(DART_PRECOMPILED_RUNTIME)
2777 // Visit objects that are being used for isolate reload.
2778 if (reload_context() != nullptr) {
2779 reload_context()->VisitObjectPointers(visitor);
2780 reload_context()->group_reload_context()->VisitObjectPointers(visitor);
2781 }
2782#endif // !defined(DART_PRECOMPILED_RUNTIME)
2783 if (ServiceIsolate::IsServiceIsolate(this)) {
2784 ServiceIsolate::VisitObjectPointers(visitor);
2785 }
2786#endif // !defined(PRODUCT)
2787
2788#if !defined(DART_PRECOMPILED_RUNTIME)
2789 // Visit objects that are being used for deoptimization.
2790 if (deopt_context() != nullptr) {
2791 deopt_context()->VisitObjectPointers(visitor);
2792 }
2793#endif // !defined(DART_PRECOMPILED_RUNTIME)
2794}
2795
2796void IsolateGroup::ReleaseStoreBuffers() {
2797 thread_registry()->ReleaseStoreBuffers();
2798}
2799
2800void Isolate::RememberLiveTemporaries() {
2801 if (mutator_thread_ != nullptr) {
2802 mutator_thread_->RememberLiveTemporaries();
2803 }
2804}
2805
2806void Isolate::DeferredMarkLiveTemporaries() {
2807 if (mutator_thread_ != nullptr) {
2808 mutator_thread_->DeferredMarkLiveTemporaries();
2809 }
2810}
2811
2812void IsolateGroup::EnableIncrementalBarrier(
2813 MarkingStack* marking_stack,
2814 MarkingStack* deferred_marking_stack) {
2815 ASSERT(marking_stack_ == nullptr);
2816 marking_stack_ = marking_stack;
2817 deferred_marking_stack_ = deferred_marking_stack;
2818 thread_registry()->AcquireMarkingStacks();
2819 ASSERT(Thread::Current()->is_marking());
2820}
2821
2822void IsolateGroup::DisableIncrementalBarrier() {
2823 thread_registry()->ReleaseMarkingStacks();
2824 ASSERT(marking_stack_ != nullptr);
2825 marking_stack_ = nullptr;
2826 deferred_marking_stack_ = nullptr;
2827}
2828
2829void IsolateGroup::ForEachIsolate(
2830 std::function<void(Isolate* isolate)> function,
2831 bool at_safepoint) {
2832 if (at_safepoint) {
2833 ASSERT(Thread::Current()->IsAtSafepoint() ||
2834 (Thread::Current()->task_kind() == Thread::kMutatorTask) ||
2835 (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
2836 (Thread::Current()->task_kind() == Thread::kCompactorTask) ||
2837 (Thread::Current()->task_kind() == Thread::kScavengerTask));
2838 for (Isolate* isolate : isolates_) {
2839 function(isolate);
2840 }
2841 } else {
2842 SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
2843 for (Isolate* isolate : isolates_) {
2844 function(isolate);
2845 }
2846 }
2847}
2848
2849Isolate* IsolateGroup::FirstIsolate() const {
2850 SafepointWriteRwLocker ml(Thread::Current(), isolates_lock_.get());
2851 return FirstIsolateLocked();
2852}
2853
2854Isolate* IsolateGroup::FirstIsolateLocked() const {
2855 return isolates_.IsEmpty() ? nullptr : isolates_.First();
2856}
2857
2858void IsolateGroup::RunWithStoppedMutatorsCallable(
2859 Callable* single_current_mutator,
2860 Callable* otherwise,
2861 bool use_force_growth_in_otherwise) {
2862 auto thread = Thread::Current();
2863
2864 if (thread->IsMutatorThread() && !FLAG_enable_isolate_groups) {
2865 single_current_mutator->Call();
2866 return;
2867 }
2868
2869 if (thread->IsAtSafepoint()) {
2870 RELEASE_ASSERT(safepoint_handler()->IsOwnedByTheThread(thread));
2871 single_current_mutator->Call();
2872 return;
2873 }
2874
2875 {
2876 SafepointReadRwLocker ml(thread, isolates_lock_.get());
2877 const bool only_one_isolate = isolates_.First() == isolates_.Last();
2878 if (thread->IsMutatorThread() && only_one_isolate) {
2879 single_current_mutator->Call();
2880 return;
2881 }
2882 }
2883
2884 // We use the more strict safepoint operation scope here (which ensures that
2885 // all other threads, including auxiliary threads are at a safepoint), even
2886 // though we only need to ensure that the mutator threads are stopped.
2887 if (use_force_growth_in_otherwise) {
2888 ForceGrowthSafepointOperationScope safepoint_scope(thread);
2889 otherwise->Call();
2890 } else {
2891 SafepointOperationScope safepoint_scope(thread);
2892 otherwise->Call();
2893 }
2894}
2895
2896void IsolateGroup::VisitObjectPointers(ObjectPointerVisitor* visitor,
2897 ValidationPolicy validate_frames) {
2898 // if class table is shared, it's stored on isolate group
2899 if (class_table() != nullptr) {
2900 // Visit objects in the class table.
2901 class_table()->VisitObjectPointers(visitor);
2902 }
2903 for (Isolate* isolate : isolates_) {
2904 isolate->VisitObjectPointers(visitor, validate_frames);
2905 }
2906 api_state()->VisitObjectPointersUnlocked(visitor);
2907 // Visit objects in the object store.
2908 if (object_store() != nullptr) {
2909 object_store()->VisitObjectPointers(visitor);
2910 }
2911 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_unlinked_calls_));
2912 if (saved_initial_field_table() != nullptr) {
2913 saved_initial_field_table()->VisitObjectPointers(visitor);
2914 }
2915 VisitStackPointers(visitor, validate_frames);
2916}
2917
2918void IsolateGroup::VisitStackPointers(ObjectPointerVisitor* visitor,
2919 ValidationPolicy validate_frames) {
2920 visitor->set_gc_root_type("stack");
2921
2922 // Visit objects in all threads (e.g. Dart stack, handles in zones), except
2923 // for the mutator threads themselves.
2924 thread_registry()->VisitObjectPointers(this, visitor, validate_frames);
2925
2926 for (Isolate* isolate : isolates_) {
2927 // Visit mutator thread, even if the isolate isn't entered/scheduled
2928 // (there might be live API handles to visit).
2929 if (isolate->mutator_thread_ != nullptr) {
2930 isolate->mutator_thread_->VisitObjectPointers(visitor, validate_frames);
2931 }
2932 }
2933
2934 visitor->clear_gc_root_type();
2935}
2936
2937void IsolateGroup::VisitObjectIdRingPointers(ObjectPointerVisitor* visitor) {
2938#if !defined(PRODUCT)
2939 for (Isolate* isolate : isolates_) {
2940 ObjectIdRing* ring = isolate->object_id_ring();
2941 if (ring != nullptr) {
2942 ring->VisitPointers(visitor);
2943 }
2944 }
2945#endif // !defined(PRODUCT)
2946}
2947
2948void IsolateGroup::VisitWeakPersistentHandles(HandleVisitor* visitor) {
2949 api_state()->VisitWeakHandlesUnlocked(visitor);
2950}
2951
2952uword IsolateGroup::FindPendingDeoptAtSafepoint(uword fp) {
2953 for (Isolate* isolate : isolates_) {
2954 for (intptr_t i = 0; i < isolate->pending_deopts_->length(); i++) {
2955 if ((*isolate->pending_deopts_)[i].fp() == fp) {
2956 return (*isolate->pending_deopts_)[i].pc();
2957 }
2958 }
2959 }
2960 FATAL("Missing pending deopt entry");
2961 return 0;
2962}
2963
2964void IsolateGroup::DeferredMarkLiveTemporaries() {
2965 ForEachIsolate(
2966 [&](Isolate* isolate) { isolate->DeferredMarkLiveTemporaries(); },
2967 /*at_safepoint=*/true);
2968}
2969
2970void IsolateGroup::RememberLiveTemporaries() {
2971 ForEachIsolate([&](Isolate* isolate) { isolate->RememberLiveTemporaries(); },
2972 /*at_safepoint=*/true);
2973}
2974
2975ClassPtr Isolate::GetClassForHeapWalkAt(intptr_t cid) {
2976 ClassPtr raw_class = nullptr;
2977#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2978 if (group()->IsReloading()) {
2979 raw_class = reload_context()->GetClassForHeapWalkAt(cid);
2980 } else {
2981 raw_class = class_table()->At(cid);
2982 }
2983#else
2984 raw_class = class_table()->At(cid);
2985#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2986 ASSERT(raw_class != nullptr);
2987 ASSERT(remapping_cids() || raw_class->ptr()->id_ == cid);
2988 return raw_class;
2989}
2990
2991intptr_t IsolateGroup::GetClassSizeForHeapWalkAt(intptr_t cid) {
2992#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
2993 if (IsReloading()) {
2994 return group_reload_context_->GetClassSizeForHeapWalkAt(cid);
2995 } else {
2996 return shared_class_table()->SizeAt(cid);
2997 }
2998#else
2999 return shared_class_table()->SizeAt(cid);
3000#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
3001}
3002
3003#if !defined(PRODUCT)
3004ObjectIdRing* Isolate::EnsureObjectIdRing() {
3005 if (object_id_ring_ == nullptr) {
3006 object_id_ring_ = new ObjectIdRing();
3007 }
3008 return object_id_ring_;
3009}
3010#endif // !defined(PRODUCT)
3011
3012void Isolate::AddPendingDeopt(uword fp, uword pc) {
3013 // GrowableArray::Add is not atomic and may be interrupt by a profiler
3014 // stack walk.
3015 MallocGrowableArray<PendingLazyDeopt>* old_pending_deopts = pending_deopts_;
3016 MallocGrowableArray<PendingLazyDeopt>* new_pending_deopts =
3017 new MallocGrowableArray<PendingLazyDeopt>(old_pending_deopts->length() +
3018 1);
3019 for (intptr_t i = 0; i < old_pending_deopts->length(); i++) {
3020 ASSERT((*old_pending_deopts)[i].fp() != fp);
3021 new_pending_deopts->Add((*old_pending_deopts)[i]);
3022 }
3023 PendingLazyDeopt deopt(fp, pc);
3024 new_pending_deopts->Add(deopt);
3025
3026 pending_deopts_ = new_pending_deopts;
3027 delete old_pending_deopts;
3028}
3029
3030uword Isolate::FindPendingDeopt(uword fp) const {
3031 for (intptr_t i = 0; i < pending_deopts_->length(); i++) {
3032 if ((*pending_deopts_)[i].fp() == fp) {
3033 return (*pending_deopts_)[i].pc();
3034 }
3035 }
3036 FATAL("Missing pending deopt entry");
3037 return 0;
3038}
3039
3040void Isolate::ClearPendingDeoptsAtOrBelow(uword fp) const {
3041 for (intptr_t i = pending_deopts_->length() - 1; i >= 0; i--) {
3042 if ((*pending_deopts_)[i].fp() <= fp) {
3043 pending_deopts_->RemoveAt(i);
3044 }
3045 }
3046}
3047
3048#ifndef PRODUCT
3049static const char* ExceptionPauseInfoToServiceEnum(Dart_ExceptionPauseInfo pi) {
3050 switch (pi) {
3051 case kPauseOnAllExceptions:
3052 return "All";
3053 case kNoPauseOnExceptions:
3054 return "None";
3055 case kPauseOnUnhandledExceptions:
3056 return "Unhandled";
3057 default:
3058 UNIMPLEMENTED();
3059 return nullptr;
3060 }
3061}
3062
3063void Isolate::PrintJSON(JSONStream* stream, bool ref) {
3064 JSONObject jsobj(stream);
3065 jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
3066 jsobj.AddServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
3067 static_cast<int64_t>(main_port()));
3068
3069 jsobj.AddProperty("name", name());
3070 jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
3071 if (ref) {
3072 return;
3073 }
3074 jsobj.AddPropertyF("_originNumber", "%" Pd64 "",
3075 static_cast<int64_t>(origin_id()));
3076 int64_t uptime_millis = UptimeMicros() / kMicrosecondsPerMillisecond;
3077 int64_t start_time = OS::GetCurrentTimeMillis() - uptime_millis;
3078 jsobj.AddPropertyTimeMillis("startTime", start_time);
3079 {
3080 JSONObject jsheap(&jsobj, "_heaps");
3081 heap()->PrintToJSONObject(Heap::kNew, &jsheap);
3082 heap()->PrintToJSONObject(Heap::kOld, &jsheap);
3083 }
3084
3085 jsobj.AddProperty("runnable", is_runnable());
3086 jsobj.AddProperty("livePorts", message_handler()->live_ports());
3087 jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit());
3088#if !defined(DART_PRECOMPILED_RUNTIME)
3089 jsobj.AddProperty("_isReloading", group()->IsReloading());
3090#endif // !defined(DART_PRECOMPILED_RUNTIME)
3091
3092 if (!is_runnable()) {
3093 // Isolate is not yet runnable.
3094 ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
3095 ServiceEvent pause_event(this, ServiceEvent::kNone);
3096 jsobj.AddProperty("pauseEvent", &pause_event);
3097 } else if (message_handler()->should_pause_on_start()) {
3098 if (message_handler()->is_paused_on_start()) {
3099 ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
3100 ServiceEvent pause_event(this, ServiceEvent::kPauseStart);
3101 jsobj.AddProperty("pauseEvent", &pause_event);
3102 } else {
3103 // Isolate is runnable but not paused on start.
3104 // Some service clients get confused if they see:
3105 // NotRunnable -> Runnable -> PausedAtStart
3106 // Treat Runnable+ShouldPauseOnStart as NotRunnable so they see:
3107 // NonRunnable -> PausedAtStart
3108 // The should_pause_on_start flag is set to false after resume.
3109 ASSERT((debugger() == nullptr) || (debugger()->PauseEvent() == nullptr));
3110 ServiceEvent pause_event(this, ServiceEvent::kNone);
3111 jsobj.AddProperty("pauseEvent", &pause_event);
3112 }
3113 } else if (message_handler()->is_paused_on_exit() &&
3114 ((debugger() == nullptr) ||
3115 (debugger()->PauseEvent() == nullptr))) {
3116 ServiceEvent pause_event(this, ServiceEvent::kPauseExit);
3117 jsobj.AddProperty("pauseEvent", &pause_event);
3118 } else if ((debugger() != nullptr) && (debugger()->PauseEvent() != nullptr) &&
3119 !ResumeRequest()) {
3120 jsobj.AddProperty("pauseEvent", debugger()->PauseEvent());
3121 } else {
3122 ServiceEvent pause_event(this, ServiceEvent::kResume);
3123
3124 if (debugger() != nullptr) {
3125 // TODO(turnidge): Don't compute a full stack trace.
3126 DebuggerStackTrace* stack = debugger()->StackTrace();
3127 if (stack->Length() > 0) {
3128 pause_event.set_top_frame(stack->FrameAt(0));
3129 }
3130 }
3131 jsobj.AddProperty("pauseEvent", &pause_event);
3132 }
3133
3134 const Library& lib = Library::Handle(object_store()->root_library());
3135 if (!lib.IsNull()) {
3136 jsobj.AddProperty("rootLib", lib);
3137 }
3138
3139 intptr_t zone_handle_count = thread_registry()->CountZoneHandles(this);
3140 intptr_t scoped_handle_count = thread_registry()->CountScopedHandles(this);
3141
3142 jsobj.AddProperty("_numZoneHandles", zone_handle_count);
3143 jsobj.AddProperty("_numScopedHandles", scoped_handle_count);
3144
3145 if (FLAG_profiler) {
3146 JSONObject tagCounters(&jsobj, "_tagCounters");
3147 vm_tag_counters()->PrintToJSONObject(&tagCounters);
3148 }
3149 if (Thread::Current()->sticky_error() != Object::null()) {
3150 Error& error = Error::Handle(Thread::Current()->sticky_error());
3151 ASSERT(!error.IsNull());
3152 jsobj.AddProperty("error", error, false);
3153 } else if (sticky_error() != Object::null()) {
3154 Error& error = Error::Handle(sticky_error());
3155 ASSERT(!error.IsNull());
3156 jsobj.AddProperty("error", error, false);
3157 }
3158
3159 {
3160 const GrowableObjectArray& libs =
3161 GrowableObjectArray::Handle(object_store()->libraries());
3162 intptr_t num_libs = libs.Length();
3163 Library& lib = Library::Handle();
3164
3165 JSONArray lib_array(&jsobj, "libraries");
3166 for (intptr_t i = 0; i < num_libs; i++) {
3167 lib ^= libs.At(i);
3168 ASSERT(!lib.IsNull());
3169 lib_array.AddValue(lib);
3170 }
3171 }
3172
3173 {
3174 JSONArray breakpoints(&jsobj, "breakpoints");
3175 if (debugger() != nullptr) {
3176 debugger()->PrintBreakpointsToJSONArray(&breakpoints);
3177 }
3178 }
3179
3180 Dart_ExceptionPauseInfo pause_info = (debugger() != nullptr)
3181 ? debugger()->GetExceptionPauseInfo()
3182 : kNoPauseOnExceptions;
3183 jsobj.AddProperty("exceptionPauseMode",
3184 ExceptionPauseInfoToServiceEnum(pause_info));
3185
3186 if (debugger() != nullptr) {
3187 JSONObject settings(&jsobj, "_debuggerSettings");
3188 debugger()->PrintSettingsToJSONObject(&settings);
3189 }
3190
3191 {
3192 GrowableObjectArray& handlers =
3193 GrowableObjectArray::Handle(registered_service_extension_handlers());
3194 if (!handlers.IsNull()) {
3195 JSONArray extensions(&jsobj, "extensionRPCs");
3196 String& handler_name = String::Handle();
3197 for (intptr_t i = 0; i < handlers.Length(); i += kRegisteredEntrySize) {
3198 handler_name ^= handlers.At(i + kRegisteredNameIndex);
3199 extensions.AddValue(handler_name.ToCString());
3200 }
3201 }
3202 }
3203
3204 jsobj.AddProperty("_threads", thread_registry());
3205
3206 {
3207 JSONObject isolate_group(&jsobj, "isolate_group");
3208 group()->PrintToJSONObject(&isolate_group, /*ref=*/true);
3209 }
3210}
3211
3212void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
3213 heap()->PrintMemoryUsageJSON(stream);
3214}
3215
3216#endif
3217
3218void Isolate::set_tag_table(const GrowableObjectArray& value) {
3219 tag_table_ = value.raw();
3220}
3221
3222void Isolate::set_current_tag(const UserTag& tag) {
3223 uword user_tag = tag.tag();
3224 ASSERT(user_tag < kUwordMax);
3225 set_user_tag(user_tag);
3226 current_tag_ = tag.raw();
3227}
3228
3229void Isolate::set_default_tag(const UserTag& tag) {
3230 default_tag_ = tag.raw();
3231}
3232
3233void Isolate::set_ic_miss_code(const Code& code) {
3234 ic_miss_code_ = code.raw();
3235}
3236
3237void Isolate::set_deoptimized_code_array(const GrowableObjectArray& value) {
3238 ASSERT(Thread::Current()->IsMutatorThread());
3239 deoptimized_code_array_ = value.raw();
3240}
3241
3242void Isolate::TrackDeoptimizedCode(const Code& code) {
3243 ASSERT(!code.IsNull());
3244 const GrowableObjectArray& deoptimized_code =
3245 GrowableObjectArray::Handle(deoptimized_code_array());
3246 if (deoptimized_code.IsNull()) {
3247 // Not tracking deoptimized code.
3248 return;
3249 }
3250 // TODO(johnmccutchan): Scan this array and the isolate's profile before
3251 // old space GC and remove the keep_code flag.
3252 deoptimized_code.Add(code);
3253}
3254
3255ErrorPtr Isolate::StealStickyError() {
3256 NoSafepointScope no_safepoint;
3257 ErrorPtr return_value = sticky_error_;
3258 sticky_error_ = Error::null();
3259 return return_value;
3260}
3261
3262#if !defined(PRODUCT)
3263void Isolate::set_pending_service_extension_calls(
3264 const GrowableObjectArray& value) {
3265 pending_service_extension_calls_ = value.raw();
3266}
3267
3268void Isolate::set_registered_service_extension_handlers(
3269 const GrowableObjectArray& value) {
3270 registered_service_extension_handlers_ = value.raw();
3271}
3272#endif // !defined(PRODUCT)
3273
3274void Isolate::AddDeoptimizingBoxedField(const Field& field) {
3275 ASSERT(Compiler::IsBackgroundCompilation());
3276 ASSERT(!field.IsOriginal());
3277 // The enclosed code allocates objects and can potentially trigger a GC,
3278 // ensure that we account for safepoints when grabbing the lock.
3279 SafepointMutexLocker ml(&field_list_mutex_);
3280 if (boxed_field_list_ == GrowableObjectArray::null()) {
3281 boxed_field_list_ = GrowableObjectArray::New(Heap::kOld);
3282 }
3283 const GrowableObjectArray& array =
3284 GrowableObjectArray::Handle(boxed_field_list_);
3285 array.Add(Field::Handle(field.Original()), Heap::kOld);
3286}
3287
3288FieldPtr Isolate::GetDeoptimizingBoxedField() {
3289 ASSERT(Thread::Current()->IsMutatorThread());
3290 SafepointMutexLocker ml(&field_list_mutex_);
3291 if (boxed_field_list_ == GrowableObjectArray::null()) {
3292 return Field::null();
3293 }
3294 const GrowableObjectArray& array =
3295 GrowableObjectArray::Handle(boxed_field_list_);
3296 if (array.Length() == 0) {
3297 return Field::null();
3298 }
3299 return Field::RawCast(array.RemoveLast());
3300}
3301
3302#ifndef PRODUCT
3303ErrorPtr Isolate::InvokePendingServiceExtensionCalls() {
3304 GrowableObjectArray& calls =
3305 GrowableObjectArray::Handle(GetAndClearPendingServiceExtensionCalls());
3306 if (calls.IsNull()) {
3307 return Error::null();
3308 }
3309 // Grab run function.
3310 const Library& developer_lib = Library::Handle(Library::DeveloperLibrary());
3311 ASSERT(!developer_lib.IsNull());
3312 const Function& run_extension = Function::Handle(
3313 developer_lib.LookupLocalFunction(Symbols::_runExtension()));
3314 ASSERT(!run_extension.IsNull());
3315
3316 const Array& arguments =
3317 Array::Handle(Array::New(kPendingEntrySize + 1, Heap::kNew));
3318 Object& result = Object::Handle();
3319 String& method_name = String::Handle();
3320 Instance& closure = Instance::Handle();
3321 Array& parameter_keys = Array::Handle();
3322 Array& parameter_values = Array::Handle();
3323 Instance& reply_port = Instance::Handle();
3324 Instance& id = Instance::Handle();
3325 for (intptr_t i = 0; i < calls.Length(); i += kPendingEntrySize) {
3326 // Grab arguments for call.
3327 closure ^= calls.At(i + kPendingHandlerIndex);
3328 ASSERT(!closure.IsNull());
3329 arguments.SetAt(kPendingHandlerIndex, closure);
3330 method_name ^= calls.At(i + kPendingMethodNameIndex);
3331 ASSERT(!method_name.IsNull());
3332 arguments.SetAt(kPendingMethodNameIndex, method_name);
3333 parameter_keys ^= calls.At(i + kPendingKeysIndex);
3334 ASSERT(!parameter_keys.IsNull());
3335 arguments.SetAt(kPendingKeysIndex, parameter_keys);
3336 parameter_values ^= calls.At(i + kPendingValuesIndex);
3337 ASSERT(!parameter_values.IsNull());
3338 arguments.SetAt(kPendingValuesIndex, parameter_values);
3339 reply_port ^= calls.At(i + kPendingReplyPortIndex);
3340 ASSERT(!reply_port.IsNull());
3341 arguments.SetAt(kPendingReplyPortIndex, reply_port);
3342 id ^= calls.At(i + kPendingIdIndex);
3343 arguments.SetAt(kPendingIdIndex, id);
3344 arguments.SetAt(kPendingEntrySize, Bool::Get(FLAG_trace_service));
3345
3346 if (FLAG_trace_service) {
3347 OS::PrintErr("[+%" Pd64 "ms] Isolate %s invoking _runExtension for %s\n",
3348 Dart::UptimeMillis(), name(), method_name.ToCString());
3349 }
3350 result = DartEntry::InvokeFunction(run_extension, arguments);
3351 if (FLAG_trace_service) {
3352 OS::PrintErr("[+%" Pd64 "ms] Isolate %s _runExtension complete for %s\n",
3353 Dart::UptimeMillis(), name(), method_name.ToCString());
3354 }
3355 // Propagate the error.
3356 if (result.IsError()) {
3357 // Remaining service extension calls are dropped.
3358 if (!result.IsUnwindError()) {
3359 // Send error back over the protocol.
3360 Service::PostError(method_name, parameter_keys, parameter_values,
3361 reply_port, id, Error::Cast(result));
3362 }
3363 return Error::Cast(result).raw();
3364 }
3365 // Drain the microtask queue.
3366 result = DartLibraryCalls::DrainMicrotaskQueue();
3367 // Propagate the error.
3368 if (result.IsError()) {
3369 // Remaining service extension calls are dropped.
3370 return Error::Cast(result).raw();
3371 }
3372 }
3373 return Error::null();
3374}
3375
3376GrowableObjectArrayPtr Isolate::GetAndClearPendingServiceExtensionCalls() {
3377 GrowableObjectArrayPtr r = pending_service_extension_calls_;
3378 pending_service_extension_calls_ = GrowableObjectArray::null();
3379 return r;
3380}
3381
3382void Isolate::AppendServiceExtensionCall(const Instance& closure,
3383 const String& method_name,
3384 const Array& parameter_keys,
3385 const Array& parameter_values,
3386 const Instance& reply_port,
3387 const Instance& id) {
3388 if (FLAG_trace_service) {
3389 OS::PrintErr("[+%" Pd64
3390 "ms] Isolate %s ENQUEUING request for extension %s\n",
3391 Dart::UptimeMillis(), name(), method_name.ToCString());
3392 }
3393 GrowableObjectArray& calls =
3394 GrowableObjectArray::Handle(pending_service_extension_calls());
3395 bool schedule_drain = false;
3396 if (calls.IsNull()) {
3397 calls = GrowableObjectArray::New();
3398 ASSERT(!calls.IsNull());
3399 set_pending_service_extension_calls(calls);
3400 schedule_drain = true;
3401 }
3402 ASSERT(kPendingHandlerIndex == 0);
3403 calls.Add(closure);
3404 ASSERT(kPendingMethodNameIndex == 1);
3405 calls.Add(method_name);
3406 ASSERT(kPendingKeysIndex == 2);
3407 calls.Add(parameter_keys);
3408 ASSERT(kPendingValuesIndex == 3);
3409 calls.Add(parameter_values);
3410 ASSERT(kPendingReplyPortIndex == 4);
3411 calls.Add(reply_port);
3412 ASSERT(kPendingIdIndex == 5);
3413 calls.Add(id);
3414
3415 if (schedule_drain) {
3416 const Array& msg = Array::Handle(Array::New(3));
3417 Object& element = Object::Handle();
3418 element = Smi::New(Message::kIsolateLibOOBMsg);
3419 msg.SetAt(0, element);
3420 element = Smi::New(Isolate::kDrainServiceExtensionsMsg);
3421 msg.SetAt(1, element);
3422 element = Smi::New(Isolate::kBeforeNextEventAction);
3423 msg.SetAt(2, element);
3424 MessageWriter writer(false);
3425 std::unique_ptr<Message> message =
3426 writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
3427 bool posted = PortMap::PostMessage(std::move(message));
3428 ASSERT(posted);
3429 }
3430}
3431
3432// This function is written in C++ and not Dart because we must do this
3433// operation atomically in the face of random OOB messages. Do not port
3434// to Dart code unless you can ensure that the operations will can be
3435// done atomically.
3436void Isolate::RegisterServiceExtensionHandler(const String& name,
3437 const Instance& closure) {
3438 if (Isolate::IsVMInternalIsolate(this)) {
3439 return;
3440 }
3441 GrowableObjectArray& handlers =
3442 GrowableObjectArray::Handle(registered_service_extension_handlers());
3443 if (handlers.IsNull()) {
3444 handlers = GrowableObjectArray::New(Heap::kOld);
3445 set_registered_service_extension_handlers(handlers);
3446 }
3447#if defined(DEBUG)
3448 {
3449 // Sanity check.
3450 const Instance& existing_handler =
3451 Instance::Handle(LookupServiceExtensionHandler(name));
3452 ASSERT(existing_handler.IsNull());
3453 }
3454#endif
3455 ASSERT(kRegisteredNameIndex == 0);
3456 handlers.Add(name, Heap::kOld);
3457 ASSERT(kRegisteredHandlerIndex == 1);
3458 handlers.Add(closure, Heap::kOld);
3459 {
3460 // Fire off an event.
3461 ServiceEvent event(this, ServiceEvent::kServiceExtensionAdded);
3462 event.set_extension_rpc(&name);
3463 Service::HandleEvent(&event);
3464 }
3465}
3466
3467// This function is written in C++ and not Dart because we must do this
3468// operation atomically in the face of random OOB messages. Do not port
3469// to Dart code unless you can ensure that the operations will can be
3470// done atomically.
3471InstancePtr Isolate::LookupServiceExtensionHandler(const String& name) {
3472 const GrowableObjectArray& handlers =
3473 GrowableObjectArray::Handle(registered_service_extension_handlers());
3474 if (handlers.IsNull()) {
3475 return Instance::null();
3476 }
3477 String& handler_name = String::Handle();
3478 for (intptr_t i = 0; i < handlers.Length(); i += kRegisteredEntrySize) {
3479 handler_name ^= handlers.At(i + kRegisteredNameIndex);
3480 ASSERT(!handler_name.IsNull());
3481 if (handler_name.Equals(name)) {
3482 return Instance::RawCast(handlers.At(i + kRegisteredHandlerIndex));
3483 }
3484 }
3485 return Instance::null();
3486}
3487
3488void Isolate::WakePauseEventHandler(Dart_Isolate isolate) {
3489 Isolate* iso = reinterpret_cast<Isolate*>(isolate);
3490 MonitorLocker ml(iso->pause_loop_monitor_);
3491 ml.Notify();
3492}
3493
3494void Isolate::PauseEventHandler() {
3495 // We are stealing a pause event (like a breakpoint) from the
3496 // embedder. We don't know what kind of thread we are on -- it
3497 // could be from our thread pool or it could be a thread from the
3498 // embedder. Sit on the current thread handling service events
3499 // until we are told to resume.
3500 if (pause_loop_monitor_ == nullptr) {
3501 pause_loop_monitor_ = new Monitor();
3502 }
3503 Dart_EnterScope();
3504 MonitorLocker ml(pause_loop_monitor_, false);
3505
3506 Dart_MessageNotifyCallback saved_notify_callback = message_notify_callback();
3507 set_message_notify_callback(Isolate::WakePauseEventHandler);
3508
3509#if !defined(DART_PRECOMPILED_RUNTIME)
3510 const bool had_isolate_reload_context = reload_context() != nullptr;
3511 const int64_t start_time_micros =
3512 !had_isolate_reload_context
3513 ? 0
3514 : reload_context()->group_reload_context()->start_time_micros();
3515#endif // !defined(DART_PRECOMPILED_RUNTIME)
3516 bool resume = false;
3517 bool handle_non_service_messages = false;
3518 while (true) {
3519 // Handle all available vm service messages, up to a resume
3520 // request.
3521 while (!resume && Dart_HasServiceMessages()) {
3522 ml.Exit();
3523 resume = Dart_HandleServiceMessages();
3524 ml.Enter();
3525 }
3526 if (resume) {
3527 break;
3528 } else {
3529 handle_non_service_messages = true;
3530 }
3531
3532#if !defined(DART_PRECOMPILED_RUNTIME)
3533 if (had_isolate_reload_context && (reload_context() == nullptr)) {
3534 if (FLAG_trace_reload) {
3535 const int64_t reload_time_micros =
3536 OS::GetCurrentMonotonicMicros() - start_time_micros;
3537 double reload_millis = MicrosecondsToMilliseconds(reload_time_micros);
3538 OS::PrintErr("Reloading has finished! (%.2f ms)\n", reload_millis);
3539 }
3540 break;
3541 }
3542#endif // !defined(DART_PRECOMPILED_RUNTIME)
3543
3544 // Wait for more service messages.
3545 Monitor::WaitResult res = ml.Wait();
3546 ASSERT(res == Monitor::kNotified);
3547 }
3548 // If any non-service messages came in, we need to notify the registered
3549 // message notify callback to check for unhandled messages. Otherwise, events
3550 // may be left unhandled until the next event comes in. See
3551 // https://github.com/dart-lang/sdk/issues/37312.
3552 if ((saved_notify_callback != nullptr) && handle_non_service_messages) {
3553 saved_notify_callback(Api::CastIsolate(this));
3554 }
3555 set_message_notify_callback(saved_notify_callback);
3556 Dart_ExitScope();
3557}
3558#endif // !PRODUCT
3559
3560void Isolate::VisitIsolates(IsolateVisitor* visitor) {
3561 if (visitor == nullptr) {
3562 return;
3563 }
3564 IsolateGroup::ForEach([&](IsolateGroup* group) {
3565 group->ForEachIsolate(
3566 [&](Isolate* isolate) { visitor->VisitIsolate(isolate); });
3567 });
3568}
3569
3570intptr_t Isolate::IsolateListLength() {
3571 intptr_t count = 0;
3572 IsolateGroup::ForEach([&](IsolateGroup* group) {
3573 group->ForEachIsolate([&](Isolate* isolate) { count++; });
3574 });
3575 return count;
3576}
3577
3578Isolate* Isolate::LookupIsolateByPort(Dart_Port port) {
3579 Isolate* match = nullptr;
3580 IsolateGroup::ForEach([&](IsolateGroup* group) {
3581 group->ForEachIsolate([&](Isolate* isolate) {
3582 if (isolate->main_port() == port) {
3583 match = isolate;
3584 }
3585 });
3586 });
3587 return match;
3588}
3589
3590std::unique_ptr<char[]> Isolate::LookupIsolateNameByPort(Dart_Port port) {
3591 MonitorLocker ml(isolate_creation_monitor_);
3592 std::unique_ptr<char[]> result;
3593 IsolateGroup::ForEach([&](IsolateGroup* group) {
3594 group->ForEachIsolate([&](Isolate* isolate) {
3595 if (isolate->main_port() == port) {
3596 const size_t len = strlen(isolate->name()) + 1;
3597 result = std::unique_ptr<char[]>(new char[len]);
3598 strncpy(result.get(), isolate->name(), len);
3599 }
3600 });
3601 });
3602 return result;
3603}
3604
3605bool Isolate::TryMarkIsolateReady(Isolate* isolate) {
3606 MonitorLocker ml(isolate_creation_monitor_);
3607 if (!creation_enabled_) {
3608 return false;
3609 }
3610 isolate->accepts_messages_ = true;
3611 return true;
3612}
3613
3614void Isolate::UnMarkIsolateReady(Isolate* isolate) {
3615 MonitorLocker ml(isolate_creation_monitor_);
3616 isolate->accepts_messages_ = false;
3617}
3618
3619void Isolate::DisableIsolateCreation() {
3620 MonitorLocker ml(isolate_creation_monitor_);
3621 creation_enabled_ = false;
3622}
3623
3624void Isolate::EnableIsolateCreation() {
3625 MonitorLocker ml(isolate_creation_monitor_);
3626 creation_enabled_ = true;
3627}
3628
3629bool Isolate::IsolateCreationEnabled() {
3630 MonitorLocker ml(isolate_creation_monitor_);
3631 return creation_enabled_;
3632}
3633
3634bool IsolateGroup::IsVMInternalIsolateGroup(const IsolateGroup* group) {
3635 // We use a name comparison here because this method can be called during
3636 // shutdown, where the actual isolate pointers might've already been cleared.
3637 const char* name = group->source()->name;
3638 return Dart::VmIsolateNameEquals(name) ||
3639#if !defined(DART_PRECOMPILED_RUNTIME)
3640 KernelIsolate::NameEquals(name) ||
3641#endif
3642 ServiceIsolate::NameEquals(name);
3643}
3644
3645void Isolate::KillLocked(LibMsgId msg_id) {
3646 Dart_CObject kill_msg;
3647 Dart_CObject* list_values[4];
3648 kill_msg.type = Dart_CObject_kArray;
3649 kill_msg.value.as_array.length = 4;
3650 kill_msg.value.as_array.values = list_values;
3651
3652 Dart_CObject oob;
3653 oob.type = Dart_CObject_kInt32;
3654 oob.value.as_int32 = Message::kIsolateLibOOBMsg;
3655 list_values[0] = &oob;
3656
3657 Dart_CObject msg_type;
3658 msg_type.type = Dart_CObject_kInt32;
3659 msg_type.value.as_int32 = msg_id;
3660 list_values[1] = &msg_type;
3661
3662 Dart_CObject cap;
3663 cap.type = Dart_CObject_kCapability;
3664 cap.value.as_capability.id = terminate_capability();
3665 list_values[2] = &cap;
3666
3667 Dart_CObject imm;
3668 imm.type = Dart_CObject_kInt32;
3669 imm.value.as_int32 = Isolate::kImmediateAction;
3670 list_values[3] = &imm;
3671
3672 {
3673 ApiMessageWriter writer;
3674 std::unique_ptr<Message> message =
3675 writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
3676 ASSERT(message != nullptr);
3677
3678 // Post the message at the given port.
3679 bool success = PortMap::PostMessage(std::move(message));
3680 ASSERT(success);
3681 }
3682}
3683
3684class IsolateKillerVisitor : public IsolateVisitor {
3685 public:
3686 explicit IsolateKillerVisitor(Isolate::LibMsgId msg_id)
3687 : target_(nullptr), msg_id_(msg_id) {}
3688
3689 IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id)
3690 : target_(isolate), msg_id_(msg_id) {
3691 ASSERT(isolate != Dart::vm_isolate());
3692 }
3693
3694 virtual ~IsolateKillerVisitor() {}
3695
3696 void VisitIsolate(Isolate* isolate) {
3697 MonitorLocker ml(Isolate::isolate_creation_monitor_);
3698 ASSERT(isolate != nullptr);
3699 if (ShouldKill(isolate)) {
3700 if (isolate->AcceptsMessagesLocked()) {
3701 isolate->KillLocked(msg_id_);
3702 }
3703 }
3704 }
3705
3706 private:
3707 bool ShouldKill(Isolate* isolate) {
3708 // If a target_ is specified, then only kill the target_.
3709 // Otherwise, don't kill the service isolate or vm isolate.
3710 return (((target_ != nullptr) && (isolate == target_)) ||
3711 ((target_ == nullptr) && !IsVMInternalIsolate(isolate)));
3712 }
3713
3714 Isolate* target_;
3715 Isolate::LibMsgId msg_id_;
3716};
3717
3718void Isolate::KillAllIsolates(LibMsgId msg_id) {
3719 IsolateKillerVisitor visitor(msg_id);
3720 VisitIsolates(&visitor);
3721}
3722
3723void Isolate::KillIfExists(Isolate* isolate, LibMsgId msg_id) {
3724 IsolateKillerVisitor visitor(isolate, msg_id);
3725 VisitIsolates(&visitor);
3726}
3727
3728void Isolate::IncrementSpawnCount() {
3729 MonitorLocker ml(&spawn_count_monitor_);
3730 spawn_count_++;
3731}
3732
3733void Isolate::DecrementSpawnCount() {
3734 MonitorLocker ml(&spawn_count_monitor_);
3735 ASSERT(spawn_count_ > 0);
3736 spawn_count_--;
3737 ml.Notify();
3738}
3739
3740void Isolate::WaitForOutstandingSpawns() {
3741 Thread* thread = Thread::Current();
3742 ASSERT(thread != NULL);
3743 MonitorLocker ml(&spawn_count_monitor_);
3744 while (spawn_count_ > 0) {
3745 ml.WaitWithSafepointCheck(thread);
3746 }
3747}
3748
3749Monitor* IsolateGroup::threads_lock() const {
3750 return thread_registry_->threads_lock();
3751}
3752
3753Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) {
3754 if (is_mutator) {
3755 group()->IncreaseMutatorCount(this);
3756 }
3757
3758 // We are about to associate the thread with an isolate group and it would
3759 // not be possible to correctly track no_safepoint_scope_depth for the
3760 // thread in the constructor/destructor of MonitorLocker,
3761 // so we create a MonitorLocker object which does not do any
3762 // no_safepoint_scope_depth increments/decrements.
3763 MonitorLocker ml(group()->threads_lock(), false);
3764
3765 // Check to make sure we don't already have a mutator thread.
3766 if (is_mutator && scheduled_mutator_thread_ != nullptr) {
3767 return nullptr;
3768 }
3769
3770 // NOTE: We cannot just use `Dart::vm_isolate() == this` here, since during
3771 // VM startup it might not have been set at this point.
3772 const bool is_vm_isolate =
3773 Dart::vm_isolate() == nullptr || Dart::vm_isolate() == this;
3774
3775 // We lazily create a [Thread] structure for the mutator thread, but we'll
3776 // reuse it until the death of the isolate.
3777 Thread* existing_mutator_thread = is_mutator ? mutator_thread_ : nullptr;
3778 if (existing_mutator_thread != nullptr) {
3779 ASSERT(existing_mutator_thread->is_mutator_thread_);
3780 }
3781
3782 // Schedule the thread into the isolate by associating a 'Thread' structure
3783 // with it (this is done while we are holding the thread registry lock).
3784 Thread* thread =
3785 group()->ScheduleThreadLocked(&ml, existing_mutator_thread, is_vm_isolate,
3786 is_mutator, bypass_safepoint);
3787 if (is_mutator) {
3788 ASSERT(mutator_thread_ == nullptr || mutator_thread_ == thread);
3789 mutator_thread_ = thread;
3790 scheduled_mutator_thread_ = thread;
3791 thread->is_mutator_thread_ = true;
3792 }
3793 thread->isolate_ = this;
3794 thread->field_table_values_ = field_table_->table();
3795
3796 return thread;
3797}
3798
3799void Isolate::UnscheduleThread(Thread* thread,
3800 bool is_mutator,
3801 bool bypass_safepoint) {
3802 {
3803 // Disassociate the 'Thread' structure and unschedule the thread
3804 // from this isolate.
3805 // We are disassociating the thread from an isolate and it would
3806 // not be possible to correctly track no_safepoint_scope_depth for the
3807 // thread in the constructor/destructor of MonitorLocker,
3808 // so we create a MonitorLocker object which does not do any
3809 // no_safepoint_scope_depth increments/decrements.
3810 MonitorLocker ml(group()->threads_lock(), false);
3811
3812 if (is_mutator) {
3813 if (thread->sticky_error() != Error::null()) {
3814 ASSERT(sticky_error_ == Error::null());
3815 sticky_error_ = thread->StealStickyError();
3816 }
3817 ASSERT(mutator_thread_ == thread);
3818 ASSERT(mutator_thread_ == scheduled_mutator_thread_);
3819 scheduled_mutator_thread_ = nullptr;
3820 } else {
3821 // We only reset the isolate pointer for non-mutator threads, since
3822 // mutator threads can still be visited during GC even if unscheduled.
3823 // See also IsolateGroup::UnscheduleThreadLocked`
3824 thread->isolate_ = nullptr;
3825 }
3826 thread->field_table_values_ = nullptr;
3827 group()->UnscheduleThreadLocked(&ml, thread, is_mutator, bypass_safepoint);
3828 }
3829 if (is_mutator) {
3830 group()->DecreaseMutatorCount(this);
3831 }
3832}
3833
3834static const char* NewConstChar(const char* chars) {
3835 size_t len = strlen(chars);
3836 char* mem = new char[len + 1];
3837 memmove(mem, chars, len + 1);
3838 return mem;
3839}
3840
3841IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
3842 Dart_Port origin_id,
3843 const char* script_url,
3844 const Function& func,
3845 SerializedObjectBuffer* message_buffer,
3846 const char* package_config,
3847 bool paused,
3848 bool errors_are_fatal,
3849 Dart_Port on_exit_port,
3850 Dart_Port on_error_port,
3851 const char* debug_name,
3852 IsolateGroup* isolate_group)
3853 : isolate_(nullptr),
3854 parent_port_(parent_port),
3855 origin_id_(origin_id),
3856 on_exit_port_(on_exit_port),
3857 on_error_port_(on_error_port),
3858 script_url_(script_url),
3859 package_config_(package_config),
3860 library_url_(nullptr),
3861 class_name_(nullptr),
3862 function_name_(nullptr),
3863 debug_name_(debug_name),
3864 isolate_group_(isolate_group),
3865 serialized_args_(nullptr),
3866 serialized_message_(message_buffer->StealMessage()),
3867 paused_(paused),
3868 errors_are_fatal_(errors_are_fatal) {
3869 const Class& cls = Class::Handle(func.Owner());
3870 const Library& lib = Library::Handle(cls.library());
3871 const String& lib_url = String::Handle(lib.url());
3872 library_url_ = NewConstChar(lib_url.ToCString());
3873
3874 String& func_name = String::Handle();
3875 func_name = func.name();
3876 function_name_ = NewConstChar(String::ScrubName(func_name));
3877 if (!cls.IsTopLevel()) {
3878 const String& class_name = String::Handle(cls.Name());
3879 class_name_ = NewConstChar(class_name.ToCString());
3880 }
3881
3882 // Inherit flags from spawning isolate.
3883 Isolate::Current()->FlagsCopyTo(isolate_flags());
3884}
3885
3886IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
3887 const char* script_url,
3888 const char* package_config,
3889 SerializedObjectBuffer* args_buffer,
3890 SerializedObjectBuffer* message_buffer,
3891 bool paused,
3892 bool errors_are_fatal,
3893 Dart_Port on_exit_port,
3894 Dart_Port on_error_port,
3895 const char* debug_name,
3896 IsolateGroup* group)
3897 : isolate_(nullptr),
3898 parent_port_(parent_port),
3899 origin_id_(ILLEGAL_PORT),
3900 on_exit_port_(on_exit_port),
3901 on_error_port_(on_error_port),
3902 script_url_(script_url),
3903 package_config_(package_config),
3904 library_url_(nullptr),
3905 class_name_(nullptr),
3906 function_name_(nullptr),
3907 debug_name_(debug_name),
3908 isolate_group_(group),
3909 serialized_args_(args_buffer->StealMessage()),
3910 serialized_message_(message_buffer->StealMessage()),
3911 isolate_flags_(),
3912 paused_(paused),
3913 errors_are_fatal_(errors_are_fatal) {
3914 function_name_ = NewConstChar("main");
3915
3916 // By default inherit flags from spawning isolate. These can be overridden
3917 // from the calling code.
3918 Isolate::Current()->FlagsCopyTo(isolate_flags());
3919}
3920
3921IsolateSpawnState::~IsolateSpawnState() {
3922 delete[] script_url_;
3923 delete[] package_config_;
3924 delete[] library_url_;
3925 delete[] class_name_;
3926 delete[] function_name_;
3927 delete[] debug_name_;
3928}
3929
3930ObjectPtr IsolateSpawnState::ResolveFunction() {
3931 Thread* thread = Thread::Current();
3932 Zone* zone = thread->zone();
3933
3934 const String& func_name = String::Handle(zone, String::New(function_name()));
3935
3936 if (library_url() == nullptr) {
3937 // Handle spawnUri lookup rules.
3938 // Check whether the root library defines a main function.
3939 const Library& lib =
3940 Library::Handle(zone, I->object_store()->root_library());
3941 Function& func = Function::Handle(zone, lib.LookupLocalFunction(func_name));
3942 if (func.IsNull()) {
3943 // Check whether main is reexported from the root library.
3944 const Object& obj = Object::Handle(zone, lib.LookupReExport(func_name));
3945 if (obj.IsFunction()) {
3946 func ^= obj.raw();
3947 }
3948 }
3949 if (func.IsNull()) {
3950 const String& msg = String::Handle(
3951 zone, String::NewFormatted(
3952 "Unable to resolve function '%s' in script '%s'.",
3953 function_name(), script_url()));
3954 return LanguageError::New(msg);
3955 }
3956 return func.raw();
3957 }
3958
3959 // Lookup the to be spawned function for the Isolate.spawn implementation.
3960 // Resolve the library.
3961 const String& lib_url = String::Handle(zone, String::New(library_url()));
3962 const Library& lib =
3963 Library::Handle(zone, Library::LookupLibrary(thread, lib_url));
3964 if (lib.IsNull() || lib.IsError()) {
3965 const String& msg = String::Handle(
3966 zone,
3967 String::NewFormatted("Unable to find library '%s'.", library_url()));
3968 return LanguageError::New(msg);
3969 }
3970
3971 // Resolve the function.
3972 if (class_name() == nullptr) {
3973 const Function& func =
3974 Function::Handle(zone, lib.LookupLocalFunction(func_name));
3975 if (func.IsNull()) {
3976 const String& msg = String::Handle(
3977 zone, String::NewFormatted(
3978 "Unable to resolve function '%s' in library '%s'.",
3979 function_name(), library_url()));
3980 return LanguageError::New(msg);
3981 }
3982 return func.raw();
3983 }
3984
3985 const String& cls_name = String::Handle(zone, String::New(class_name()));
3986 const Class& cls = Class::Handle(zone, lib.LookupLocalClass(cls_name));
3987 if (cls.IsNull()) {
3988 const String& msg = String::Handle(
3989 zone, String::NewFormatted(
3990 "Unable to resolve class '%s' in library '%s'.", class_name(),
3991 (library_url() != nullptr ? library_url() : script_url())));
3992 return LanguageError::New(msg);
3993 }
3994 const Function& func =
3995 Function::Handle(zone, cls.LookupStaticFunctionAllowPrivate(func_name));
3996 if (func.IsNull()) {
3997 const String& msg = String::Handle(
3998 zone, String::NewFormatted(
3999 "Unable to resolve static method '%s.%s' in library '%s'.",
4000 class_name(), function_name(),
4001 (library_url() != nullptr ? library_url() : script_url())));
4002 return LanguageError::New(msg);
4003 }
4004 return func.raw();
4005}
4006
4007InstancePtr IsolateSpawnState::BuildArgs(Thread* thread) {
4008 return DeserializeMessage(thread, serialized_args_.get());
4009}
4010
4011InstancePtr IsolateSpawnState::BuildMessage(Thread* thread) {
4012 return DeserializeMessage(thread, serialized_message_.get());
4013}
4014
4015} // namespace dart
4016