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#ifndef RUNTIME_VM_ISOLATE_H_
6#define RUNTIME_VM_ISOLATE_H_
7
8#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
9#error "Should not include runtime"
10#endif
11
12#include <functional>
13#include <memory>
14#include <utility>
15
16#include "include/dart_api.h"
17#include "platform/assert.h"
18#include "platform/atomic.h"
19#include "vm/base_isolate.h"
20#include "vm/class_table.h"
21#include "vm/dispatch_table.h"
22#include "vm/exceptions.h"
23#include "vm/ffi_callback_metadata.h"
24#include "vm/field_table.h"
25#include "vm/fixed_cache.h"
26#include "vm/growable_array.h"
27#include "vm/handles.h"
28#include "vm/heap/verifier.h"
29#include "vm/intrusive_dlist.h"
30#include "vm/megamorphic_cache_table.h"
31#include "vm/metrics.h"
32#include "vm/os_thread.h"
33#include "vm/random.h"
34#include "vm/tags.h"
35#include "vm/thread.h"
36#include "vm/thread_pool.h"
37#include "vm/thread_stack_resource.h"
38#include "vm/token_position.h"
39#include "vm/virtual_memory.h"
40
41namespace dart {
42
43// Forward declarations.
44class ApiState;
45class BackgroundCompiler;
46class Become;
47class Capability;
48class CodeIndexTable;
49class Debugger;
50class DeoptContext;
51class ExternalTypedData;
52class GroupDebugger;
53class HandleScope;
54class HandleVisitor;
55class Heap;
56class ICData;
57class IsolateGroupReloadContext;
58class IsolateObjectStore;
59class IsolateProfilerData;
60class ProgramReloadContext;
61class Log;
62class Message;
63class MessageHandler;
64class MonitorLocker;
65class Mutex;
66class Object;
67class ObjectIdRing;
68class ObjectPointerVisitor;
69class ObjectStore;
70class PersistentHandle;
71class RwLock;
72class SafepointRwLock;
73class SafepointHandler;
74class SampleBuffer;
75class SampleBlock;
76class SampleBlockBuffer;
77class SendPort;
78class SerializedObjectBuffer;
79class ServiceIdZone;
80class Simulator;
81class StackResource;
82class StackZone;
83class StoreBuffer;
84class StubCode;
85class ThreadRegistry;
86class UserTag;
87class WeakTable;
88
89class IsolateVisitor {
90 public:
91 IsolateVisitor() {}
92 virtual ~IsolateVisitor() {}
93
94 virtual void VisitIsolate(Isolate* isolate) = 0;
95
96 protected:
97 // Returns true if |isolate| is the VM or service isolate.
98 bool IsSystemIsolate(Isolate* isolate) const;
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(IsolateVisitor);
102};
103
104class Callable : public ValueObject {
105 public:
106 Callable() {}
107 virtual ~Callable() {}
108
109 virtual void Call() = 0;
110
111 private:
112 DISALLOW_COPY_AND_ASSIGN(Callable);
113};
114
115template <typename T>
116class LambdaCallable : public Callable {
117 public:
118 explicit LambdaCallable(T& lambda) : lambda_(lambda) {}
119 void Call() { lambda_(); }
120
121 private:
122 T& lambda_;
123 DISALLOW_COPY_AND_ASSIGN(LambdaCallable);
124};
125
126// Fixed cache for exception handler lookup.
127typedef FixedCache<intptr_t, ExceptionHandlerInfo, 16> HandlerInfoCache;
128// Fixed cache for catch entry state lookup.
129typedef FixedCache<intptr_t, CatchEntryMovesRefPtr, 16> CatchEntryMovesCache;
130
131// List of Isolate flags with corresponding members of Dart_IsolateFlags and
132// corresponding global command line flags.
133#define BOOL_ISOLATE_FLAG_LIST(V) BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)
134
135#define BOOL_ISOLATE_GROUP_FLAG_LIST(V) \
136 BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(V) \
137 BOOL_ISOLATE_GROUP_FLAG_LIST_CUSTOM_GETTER(V)
138
139// List of Isolate flags with default getters.
140//
141// V(when, name, bit-name, Dart_IsolateFlags-name, command-line-flag-name)
142//
143#define BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(V) \
144 V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false) \
145 V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts) \
146 V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
147 FLAG_use_field_guards) \
148 V(PRODUCT, should_load_vmservice_library, ShouldLoadVmService, \
149 load_vmservice_library, false) \
150 V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
151 V(NONPRODUCT, snapshot_is_dontneed_safe, SnapshotIsDontNeedSafe, \
152 snapshot_is_dontneed_safe, false) \
153 V(NONPRODUCT, branch_coverage, BranchCoverage, branch_coverage, \
154 FLAG_branch_coverage)
155
156#define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V) \
157 V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code, false) \
158 V(PRODUCT, is_system_isolate, IsSystemIsolate, is_system_isolate, false)
159
160// List of Isolate flags with custom getters named #name().
161//
162// V(when, name, bit-name, Dart_IsolateFlags-name, default_value)
163//
164#define BOOL_ISOLATE_GROUP_FLAG_LIST_CUSTOM_GETTER(V) \
165 V(PRODUCT, null_safety, NullSafety, null_safety, false)
166
167// Represents the information used for spawning the first isolate within an
168// isolate group. All isolates within a group will refer to this
169// [IsolateGroupSource].
170class IsolateGroupSource {
171 public:
172 IsolateGroupSource(const char* script_uri,
173 const char* name,
174 const uint8_t* snapshot_data,
175 const uint8_t* snapshot_instructions,
176 const uint8_t* kernel_buffer,
177 intptr_t kernel_buffer_size,
178 Dart_IsolateFlags flags)
179 : script_uri(script_uri == nullptr ? nullptr : Utils::StrDup(s: script_uri)),
180 name(Utils::StrDup(s: name)),
181 snapshot_data(snapshot_data),
182 snapshot_instructions(snapshot_instructions),
183 kernel_buffer(kernel_buffer),
184 kernel_buffer_size(kernel_buffer_size),
185 flags(flags),
186 script_kernel_buffer(nullptr),
187 script_kernel_size(-1),
188 loaded_blobs_(nullptr),
189 num_blob_loads_(0) {}
190 ~IsolateGroupSource() {
191 free(ptr: script_uri);
192 free(ptr: name);
193 }
194
195 void add_loaded_blob(Zone* zone_,
196 const ExternalTypedData& external_typed_data);
197
198 // The arguments used for spawning in
199 // `Dart_CreateIsolateGroupFromKernel` / `Dart_CreateIsolate`.
200 char* script_uri;
201 char* name;
202 const uint8_t* snapshot_data;
203 const uint8_t* snapshot_instructions;
204 const uint8_t* kernel_buffer;
205 const intptr_t kernel_buffer_size;
206 Dart_IsolateFlags flags;
207
208 // The kernel buffer used in `Dart_LoadScriptFromKernel`.
209 const uint8_t* script_kernel_buffer;
210 intptr_t script_kernel_size;
211
212 // List of weak pointers to external typed data for loaded blobs.
213 ArrayPtr loaded_blobs_;
214 intptr_t num_blob_loads_;
215};
216
217// Tracks idle time and notifies heap when idle time expired.
218class IdleTimeHandler : public ValueObject {
219 public:
220 IdleTimeHandler() {}
221
222 // Initializes the idle time handler with the given [heap], to which
223 // idle notifications will be sent.
224 void InitializeWithHeap(Heap* heap);
225
226 // Returns whether the caller should check for idle timeouts.
227 bool ShouldCheckForIdle();
228
229 // Declares that the idle time should be reset to now.
230 void UpdateStartIdleTime();
231
232 // Returns whether idle time expired and [NotifyIdle] should be called.
233 bool ShouldNotifyIdle(int64_t* expiry);
234
235 // Notifies the heap that now is a good time to do compactions and indicates
236 // we have time for the GC until [deadline].
237 void NotifyIdle(int64_t deadline);
238
239 // Calls [NotifyIdle] with the default deadline.
240 void NotifyIdleUsingDefaultDeadline();
241
242 private:
243 friend class DisableIdleTimerScope;
244
245 Mutex mutex_;
246 Heap* heap_ = nullptr;
247 intptr_t disabled_counter_ = 0;
248 int64_t idle_start_time_ = 0;
249};
250
251// Disables firing of the idle timer while this object is alive.
252class DisableIdleTimerScope : public ValueObject {
253 public:
254 explicit DisableIdleTimerScope(IdleTimeHandler* handler);
255 ~DisableIdleTimerScope();
256
257 private:
258 IdleTimeHandler* handler_;
259};
260
261class MutatorThreadPool : public ThreadPool {
262 public:
263 MutatorThreadPool(IsolateGroup* isolate_group, intptr_t max_pool_size)
264 : ThreadPool(max_pool_size), isolate_group_(isolate_group) {}
265 virtual ~MutatorThreadPool() {}
266
267 protected:
268 virtual void OnEnterIdleLocked(MonitorLocker* ml);
269
270 private:
271 void NotifyIdle();
272
273 IsolateGroup* isolate_group_ = nullptr;
274};
275
276// Represents an isolate group and is shared among all isolates within a group.
277class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
278 public:
279 IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
280 void* embedder_data,
281 ObjectStore* object_store,
282 Dart_IsolateFlags api_flags);
283 IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
284 void* embedder_data,
285 Dart_IsolateFlags api_flags);
286 ~IsolateGroup();
287
288 void RehashConstants(Become* become);
289#if defined(DEBUG)
290 void ValidateClassTable();
291#endif
292
293 IsolateGroupSource* source() const { return source_.get(); }
294 std::shared_ptr<IsolateGroupSource> shareable_source() const {
295 return source_;
296 }
297 void* embedder_data() const { return embedder_data_; }
298
299 bool initial_spawn_successful() { return initial_spawn_successful_; }
300 void set_initial_spawn_successful() { initial_spawn_successful_ = true; }
301
302 Heap* heap() const { return heap_.get(); }
303
304 BackgroundCompiler* background_compiler() const {
305#if defined(DART_PRECOMPILED_RUNTIME)
306 return nullptr;
307#else
308 return background_compiler_.get();
309#endif
310 }
311#if !defined(DART_PRECOMPILED_RUNTIME)
312 intptr_t optimization_counter_threshold() const {
313 if (IsSystemIsolateGroup(group: this)) {
314 return kDefaultOptimizationCounterThreshold;
315 }
316 return FLAG_optimization_counter_threshold;
317 }
318#endif
319
320#if !defined(PRODUCT)
321 GroupDebugger* debugger() const { return debugger_; }
322#endif
323
324 IdleTimeHandler* idle_time_handler() { return &idle_time_handler_; }
325
326 // Returns true if this is the first isolate registered.
327 void RegisterIsolate(Isolate* isolate);
328 void UnregisterIsolate(Isolate* isolate);
329 // Returns `true` if this was the last isolate and the caller is responsible
330 // for deleting the isolate group.
331 bool UnregisterIsolateDecrementCount();
332
333 bool ContainsOnlyOneIsolate();
334
335 void RunWithLockedGroup(std::function<void()> fun);
336
337 ThreadRegistry* thread_registry() const { return thread_registry_.get(); }
338 SafepointHandler* safepoint_handler() { return safepoint_handler_.get(); }
339
340 void CreateHeap(bool is_vm_isolate, bool is_service_or_kernel_isolate);
341 void SetupImagePage(const uint8_t* snapshot_buffer, bool is_executable);
342 void Shutdown();
343
344#define ISOLATE_METRIC_ACCESSOR(type, variable, name, unit) \
345 type* Get##variable##Metric() { return &metric_##variable##_; }
346 ISOLATE_GROUP_METRIC_LIST(ISOLATE_METRIC_ACCESSOR);
347#undef ISOLATE_METRIC_ACCESSOR
348
349#if !defined(PRODUCT)
350 void UpdateLastAllocationProfileAccumulatorResetTimestamp() {
351 last_allocationprofile_accumulator_reset_timestamp_ =
352 OS::GetCurrentTimeMillis();
353 }
354
355 int64_t last_allocationprofile_accumulator_reset_timestamp() const {
356 return last_allocationprofile_accumulator_reset_timestamp_;
357 }
358
359 void UpdateLastAllocationProfileGCTimestamp() {
360 last_allocationprofile_gc_timestamp_ = OS::GetCurrentTimeMillis();
361 }
362
363 int64_t last_allocationprofile_gc_timestamp() const {
364 return last_allocationprofile_gc_timestamp_;
365 }
366#endif // !defined(PRODUCT)
367
368 DispatchTable* dispatch_table() const { return dispatch_table_.get(); }
369 void set_dispatch_table(DispatchTable* table) {
370 dispatch_table_.reset(p: table);
371 }
372 const uint8_t* dispatch_table_snapshot() const {
373 return dispatch_table_snapshot_;
374 }
375 void set_dispatch_table_snapshot(const uint8_t* snapshot) {
376 dispatch_table_snapshot_ = snapshot;
377 }
378 intptr_t dispatch_table_snapshot_size() const {
379 return dispatch_table_snapshot_size_;
380 }
381 void set_dispatch_table_snapshot_size(intptr_t size) {
382 dispatch_table_snapshot_size_ = size;
383 }
384
385 ClassTableAllocator* class_table_allocator() {
386 return &class_table_allocator_;
387 }
388
389 static intptr_t class_table_offset() {
390 COMPILE_ASSERT(sizeof(IsolateGroup::class_table_) == kWordSize);
391 return OFFSET_OF(IsolateGroup, class_table_);
392 }
393
394 ClassPtr* cached_class_table_table() {
395 return cached_class_table_table_.load();
396 }
397 void set_cached_class_table_table(ClassPtr* cached_class_table_table) {
398 cached_class_table_table_.store(arg: cached_class_table_table);
399 }
400 static intptr_t cached_class_table_table_offset() {
401 COMPILE_ASSERT(sizeof(IsolateGroup::cached_class_table_table_) ==
402 kWordSize);
403 return OFFSET_OF(IsolateGroup, cached_class_table_table_);
404 }
405
406 void set_object_store(ObjectStore* object_store);
407 static intptr_t object_store_offset() {
408 COMPILE_ASSERT(sizeof(IsolateGroup::object_store_) == kWordSize);
409 return OFFSET_OF(IsolateGroup, object_store_);
410 }
411
412 void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
413 const char** obfuscation_map() const { return obfuscation_map_; }
414
415 Random* random() { return &random_; }
416
417 bool is_system_isolate_group() const { return is_system_isolate_group_; }
418
419 // IsolateGroup-specific flag handling.
420 static void FlagsInitialize(Dart_IsolateFlags* api_flags);
421 void FlagsCopyTo(Dart_IsolateFlags* api_flags);
422 void FlagsCopyFrom(const Dart_IsolateFlags& api_flags);
423
424#if defined(DART_PRECOMPILER)
425#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_field)
426#else
427#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_flag)
428#endif
429
430#if !defined(PRODUCT)
431#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_field)
432#else
433#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_flag)
434#endif
435
436#define FLAG_FOR_PRODUCT(from_field, from_flag) (from_field)
437
438#define DECLARE_GETTER(when, name, bitname, isolate_flag_name, flag_name) \
439 bool name() const { \
440 return FLAG_FOR_##when(bitname##Bit::decode(isolate_group_flags_), \
441 flag_name); \
442 }
443 BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(DECLARE_GETTER)
444#undef FLAG_FOR_NONPRODUCT
445#undef FLAG_FOR_PRECOMPILER
446#undef FLAG_FOR_PRODUCT
447#undef DECLARE_GETTER
448
449 bool null_safety_not_set() const {
450 return !NullSafetySetBit::decode(value: isolate_group_flags_);
451 }
452
453 bool null_safety() const {
454 ASSERT(!null_safety_not_set());
455 return NullSafetyBit::decode(value: isolate_group_flags_);
456 }
457
458 void set_null_safety(bool null_safety) {
459 isolate_group_flags_ = NullSafetySetBit::update(value: true, original: isolate_group_flags_);
460 isolate_group_flags_ =
461 NullSafetyBit::update(value: null_safety, original: isolate_group_flags_);
462 }
463
464 bool use_strict_null_safety_checks() const {
465 return null_safety() || FLAG_strict_null_safety_checks;
466 }
467
468 bool should_load_vmservice() const {
469 return ShouldLoadVmServiceBit::decode(value: isolate_group_flags_);
470 }
471 void set_should_load_vmservice(bool value) {
472 isolate_group_flags_ =
473 ShouldLoadVmServiceBit::update(value, original: isolate_group_flags_);
474 }
475
476 void set_asserts(bool value) {
477 isolate_group_flags_ =
478 EnableAssertsBit::update(value, original: isolate_group_flags_);
479 }
480
481 void set_branch_coverage(bool value) {
482 isolate_group_flags_ =
483 BranchCoverageBit::update(value, original: isolate_group_flags_);
484 }
485
486#if !defined(PRODUCT)
487#if !defined(DART_PRECOMPILED_RUNTIME)
488 bool HasAttemptedReload() const {
489 return HasAttemptedReloadBit::decode(value: isolate_group_flags_);
490 }
491 void SetHasAttemptedReload(bool value) {
492 isolate_group_flags_ =
493 HasAttemptedReloadBit::update(value, original: isolate_group_flags_);
494 }
495 void MaybeIncreaseReloadEveryNStackOverflowChecks();
496 intptr_t reload_every_n_stack_overflow_checks() const {
497 return reload_every_n_stack_overflow_checks_;
498 }
499#else
500 bool HasAttemptedReload() const { return false; }
501#endif // !defined(DART_PRECOMPILED_RUNTIME)
502#endif // !defined(PRODUCT)
503
504#if defined(PRODUCT)
505 void set_use_osr(bool use_osr) { ASSERT(!use_osr); }
506#else // defined(PRODUCT)
507 void set_use_osr(bool use_osr) {
508 isolate_group_flags_ = UseOsrBit::update(value: use_osr, original: isolate_group_flags_);
509 }
510#endif // defined(PRODUCT)
511
512 // Class table for the program loaded into this isolate group.
513 //
514 // This table is modified by kernel loading.
515 ClassTable* class_table() const {
516 return class_table_;
517 }
518
519 // Class table used for heap walks by GC visitors. Usually it
520 // is the same table as one in |class_table_|, except when in the
521 // middle of the reload.
522 //
523 // See comment for |ClassTable| class for more details.
524 ClassTable* heap_walk_class_table() const {
525 return heap_walk_class_table_;
526 }
527
528 void CloneClassTableForReload();
529 void RestoreOriginalClassTable();
530 void DropOriginalClassTable();
531
532 StoreBuffer* store_buffer() const { return store_buffer_.get(); }
533 ObjectStore* object_store() const { return object_store_.get(); }
534 Mutex* symbols_mutex() { return &symbols_mutex_; }
535 Mutex* type_canonicalization_mutex() { return &type_canonicalization_mutex_; }
536 Mutex* type_arguments_canonicalization_mutex() {
537 return &type_arguments_canonicalization_mutex_;
538 }
539 Mutex* subtype_test_cache_mutex() { return &subtype_test_cache_mutex_; }
540 Mutex* megamorphic_table_mutex() { return &megamorphic_table_mutex_; }
541 Mutex* type_feedback_mutex() { return &type_feedback_mutex_; }
542 Mutex* patchable_call_mutex() { return &patchable_call_mutex_; }
543 Mutex* constant_canonicalization_mutex() {
544 return &constant_canonicalization_mutex_;
545 }
546 Mutex* kernel_data_lib_cache_mutex() { return &kernel_data_lib_cache_mutex_; }
547 Mutex* kernel_data_class_cache_mutex() {
548 return &kernel_data_class_cache_mutex_;
549 }
550 Mutex* kernel_constants_mutex() { return &kernel_constants_mutex_; }
551
552#if defined(DART_PRECOMPILED_RUNTIME)
553 Mutex* unlinked_call_map_mutex() { return &unlinked_call_map_mutex_; }
554#endif
555
556#if !defined(DART_PRECOMPILED_RUNTIME)
557 Mutex* initializer_functions_mutex() { return &initializer_functions_mutex_; }
558#endif // !defined(DART_PRECOMPILED_RUNTIME)
559
560 SafepointRwLock* program_lock() { return program_lock_.get(); }
561
562 static inline IsolateGroup* Current() {
563 Thread* thread = Thread::Current();
564 return thread == nullptr ? nullptr : thread->isolate_group();
565 }
566
567 void IncreaseMutatorCount(Isolate* mutator, bool is_nested_reenter);
568 void DecreaseMutatorCount(Isolate* mutator, bool is_nested_exit);
569 intptr_t MutatorCount() const {
570 MonitorLocker ml(active_mutators_monitor_.get());
571 return active_mutators_;
572 }
573
574 bool HasTagHandler() const { return library_tag_handler() != nullptr; }
575 ObjectPtr CallTagHandler(Dart_LibraryTag tag,
576 const Object& arg1,
577 const Object& arg2);
578 Dart_LibraryTagHandler library_tag_handler() const {
579 return library_tag_handler_;
580 }
581 void set_library_tag_handler(Dart_LibraryTagHandler handler) {
582 library_tag_handler_ = handler;
583 }
584 Dart_DeferredLoadHandler deferred_load_handler() const {
585 return deferred_load_handler_;
586 }
587 void set_deferred_load_handler(Dart_DeferredLoadHandler handler) {
588 deferred_load_handler_ = handler;
589 }
590
591 // Prepares all threads in an isolate for Garbage Collection.
592 void ReleaseStoreBuffers();
593 void EnableIncrementalBarrier(MarkingStack* marking_stack,
594 MarkingStack* deferred_marking_stack);
595 void DisableIncrementalBarrier();
596
597 MarkingStack* marking_stack() const { return marking_stack_; }
598 MarkingStack* deferred_marking_stack() const {
599 return deferred_marking_stack_;
600 }
601
602 // Runs the given [function] on every isolate in the isolate group.
603 //
604 // During the duration of this function, no new isolates can be added or
605 // removed.
606 //
607 // If [at_safepoint] is `true`, then the entire isolate group must be in a
608 // safepoint. There is therefore no reason to guard against other threads
609 // adding/removing isolates, so no locks will be held.
610 void ForEachIsolate(std::function<void(Isolate* isolate)> function,
611 bool at_safepoint = false);
612 Isolate* FirstIsolate() const;
613 Isolate* FirstIsolateLocked() const;
614
615 // Ensures mutators are stopped during execution of the provided function.
616 //
617 // If the current thread is the only mutator in the isolate group,
618 // [single_current_mutator] will be called. Otherwise [otherwise] will be
619 // called inside a [SafepointOperationsScope] (or
620 // [ForceGrowthSafepointOperationScope] if [use_force_growth_in_otherwise]
621 // is set).
622 //
623 // During the duration of this function, no new isolates can be added to the
624 // isolate group.
625 void RunWithStoppedMutatorsCallable(
626 Callable* single_current_mutator,
627 Callable* otherwise,
628 bool use_force_growth_in_otherwise = false);
629
630 template <typename T, typename S>
631 void RunWithStoppedMutators(T single_current_mutator,
632 S otherwise,
633 bool use_force_growth_in_otherwise = false) {
634 LambdaCallable<T> single_callable(single_current_mutator);
635 LambdaCallable<S> otherwise_callable(otherwise);
636 RunWithStoppedMutatorsCallable(single_current_mutator: &single_callable, otherwise: &otherwise_callable,
637 use_force_growth_in_otherwise);
638 }
639
640 template <typename T>
641 void RunWithStoppedMutators(T function, bool use_force_growth = false) {
642 LambdaCallable<T> callable(function);
643 RunWithStoppedMutatorsCallable(single_current_mutator: &callable, otherwise: &callable, use_force_growth_in_otherwise: use_force_growth);
644 }
645
646#ifndef PRODUCT
647 void PrintJSON(JSONStream* stream, bool ref = true);
648 void PrintToJSONObject(JSONObject* jsobj, bool ref);
649
650 // Creates an object with the total heap memory usage statistics for this
651 // isolate group.
652 void PrintMemoryUsageJSON(JSONStream* stream);
653#endif
654
655#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
656 // By default the reload context is deleted. This parameter allows
657 // the caller to delete is separately if it is still needed.
658 bool ReloadSources(JSONStream* js,
659 bool force_reload,
660 const char* root_script_url = nullptr,
661 const char* packages_url = nullptr,
662 bool dont_delete_reload_context = false);
663
664 // If provided, the VM takes ownership of kernel_buffer.
665 bool ReloadKernel(JSONStream* js,
666 bool force_reload,
667 const uint8_t* kernel_buffer = nullptr,
668 intptr_t kernel_buffer_size = 0,
669 bool dont_delete_reload_context = false);
670
671 void set_last_reload_timestamp(int64_t value) {
672 last_reload_timestamp_ = value;
673 }
674 int64_t last_reload_timestamp() const { return last_reload_timestamp_; }
675
676 IsolateGroupReloadContext* reload_context() {
677 return group_reload_context_.get();
678 }
679 ProgramReloadContext* program_reload_context() {
680 return program_reload_context_;
681 }
682
683 void DeleteReloadContext();
684 bool CanReload();
685#else
686 bool CanReload() { return false; }
687#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
688
689 bool IsReloading() const {
690#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
691 return group_reload_context_ != nullptr;
692#else
693 return false;
694#endif
695 }
696
697 Become* become() const { return become_; }
698 void set_become(Become* become) { become_ = become; }
699
700 uint64_t id() const { return id_; }
701
702 static void Init();
703 static void Cleanup();
704
705 static void ForEach(std::function<void(IsolateGroup*)> action);
706 static void RunWithIsolateGroup(uint64_t id,
707 std::function<void(IsolateGroup*)> action,
708 std::function<void()> not_found);
709
710 // Manage list of existing isolate groups.
711 static void RegisterIsolateGroup(IsolateGroup* isolate_group);
712 static void UnregisterIsolateGroup(IsolateGroup* isolate_group);
713
714 static bool HasApplicationIsolateGroups();
715 static bool HasOnlyVMIsolateGroup();
716 static bool IsSystemIsolateGroup(const IsolateGroup* group);
717
718 int64_t UptimeMicros() const;
719
720 ApiState* api_state() const { return api_state_.get(); }
721
722 // Visit all object pointers. Caller must ensure concurrent sweeper is not
723 // running, and the visitor must not allocate.
724 void VisitObjectPointers(ObjectPointerVisitor* visitor,
725 ValidationPolicy validate_frames);
726 void VisitSharedPointers(ObjectPointerVisitor* visitor);
727 void VisitStackPointers(ObjectPointerVisitor* visitor,
728 ValidationPolicy validate_frames);
729 void VisitObjectIdRingPointers(ObjectPointerVisitor* visitor);
730 void VisitWeakPersistentHandles(HandleVisitor* visitor);
731
732 // In precompilation we finalize all regular classes before compiling.
733 bool all_classes_finalized() const {
734 return AllClassesFinalizedBit::decode(value: isolate_group_flags_);
735 }
736 void set_all_classes_finalized(bool value) {
737 isolate_group_flags_ =
738 AllClassesFinalizedBit::update(value, original: isolate_group_flags_);
739 }
740
741 bool remapping_cids() const {
742 return RemappingCidsBit::decode(value: isolate_group_flags_);
743 }
744 void set_remapping_cids(bool value) {
745 isolate_group_flags_ =
746 RemappingCidsBit::update(value, original: isolate_group_flags_);
747 }
748
749 void RememberLiveTemporaries();
750 void DeferredMarkLiveTemporaries();
751
752 ArrayPtr saved_unlinked_calls() const { return saved_unlinked_calls_; }
753 void set_saved_unlinked_calls(const Array& saved_unlinked_calls);
754
755 FieldTable* initial_field_table() const { return initial_field_table_.get(); }
756 std::shared_ptr<FieldTable> initial_field_table_shareable() {
757 return initial_field_table_;
758 }
759 void set_initial_field_table(std::shared_ptr<FieldTable> field_table) {
760 initial_field_table_ = field_table;
761 }
762
763 MutatorThreadPool* thread_pool() { return thread_pool_.get(); }
764
765 void RegisterClass(const Class& cls);
766 void RegisterStaticField(const Field& field, const Object& initial_value);
767 void FreeStaticField(const Field& field);
768
769 Isolate* EnterTemporaryIsolate();
770 static void ExitTemporaryIsolate();
771
772 private:
773 friend class Dart; // For `object_store_ = ` in Dart::Init
774 friend class Heap;
775 friend class StackFrame; // For `[isolates_].First()`.
776 // For `object_store_shared_untag()`, `class_table_shared_untag()`
777 friend class Isolate;
778
779#define ISOLATE_GROUP_FLAG_BITS(V) \
780 V(AllClassesFinalized) \
781 V(EnableAsserts) \
782 V(HasAttemptedReload) \
783 V(NullSafety) \
784 V(RemappingCids) \
785 V(ShouldLoadVmService) \
786 V(NullSafetySet) \
787 V(Obfuscate) \
788 V(UseFieldGuards) \
789 V(UseOsr) \
790 V(SnapshotIsDontNeedSafe) \
791 V(BranchCoverage)
792
793 // Isolate group specific flags.
794 enum FlagBits {
795#define DECLARE_BIT(Name) k##Name##Bit,
796 ISOLATE_GROUP_FLAG_BITS(DECLARE_BIT)
797#undef DECLARE_BIT
798 };
799
800#define DECLARE_BITFIELD(Name) \
801 class Name##Bit : public BitField<uint32_t, bool, k##Name##Bit, 1> {};
802 ISOLATE_GROUP_FLAG_BITS(DECLARE_BITFIELD)
803#undef DECLARE_BITFIELD
804
805 void set_heap(std::unique_ptr<Heap> value);
806
807 // Accessed from generated code.
808 ClassTable* class_table_;
809 AcqRelAtomic<ClassPtr*> cached_class_table_table_;
810 std::unique_ptr<ObjectStore> object_store_;
811 // End accessed from generated code.
812
813 ClassTableAllocator class_table_allocator_;
814 ClassTable* heap_walk_class_table_;
815
816 const char** obfuscation_map_ = nullptr;
817
818 bool is_vm_isolate_heap_ = false;
819 void* embedder_data_ = nullptr;
820
821 IdleTimeHandler idle_time_handler_;
822 std::unique_ptr<MutatorThreadPool> thread_pool_;
823 std::unique_ptr<SafepointRwLock> isolates_lock_;
824 IntrusiveDList<Isolate> isolates_;
825 intptr_t isolate_count_ = 0;
826 bool initial_spawn_successful_ = false;
827 Dart_LibraryTagHandler library_tag_handler_ = nullptr;
828 Dart_DeferredLoadHandler deferred_load_handler_ = nullptr;
829 int64_t start_time_micros_;
830 bool is_system_isolate_group_;
831 Random random_;
832
833#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
834 int64_t last_reload_timestamp_;
835 std::shared_ptr<IsolateGroupReloadContext> group_reload_context_;
836 // Per-isolate-group copy of FLAG_reload_every.
837 RelaxedAtomic<intptr_t> reload_every_n_stack_overflow_checks_;
838 ProgramReloadContext* program_reload_context_ = nullptr;
839#endif
840 Become* become_ = nullptr;
841
842#define ISOLATE_METRIC_VARIABLE(type, variable, name, unit) \
843 type metric_##variable##_;
844 ISOLATE_GROUP_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
845#undef ISOLATE_METRIC_VARIABLE
846
847#if !defined(PRODUCT)
848 // Timestamps of last operation via service.
849 int64_t last_allocationprofile_accumulator_reset_timestamp_ = 0;
850 int64_t last_allocationprofile_gc_timestamp_ = 0;
851
852#endif // !defined(PRODUCT)
853
854 MarkingStack* marking_stack_ = nullptr;
855 MarkingStack* deferred_marking_stack_ = nullptr;
856 std::shared_ptr<IsolateGroupSource> source_;
857 std::unique_ptr<ApiState> api_state_;
858 std::unique_ptr<ThreadRegistry> thread_registry_;
859 std::unique_ptr<SafepointHandler> safepoint_handler_;
860
861 static RwLock* isolate_groups_rwlock_;
862 static IntrusiveDList<IsolateGroup>* isolate_groups_;
863 static Random* isolate_group_random_;
864
865 uint64_t id_ = 0;
866
867 std::unique_ptr<StoreBuffer> store_buffer_;
868 std::unique_ptr<Heap> heap_;
869 std::unique_ptr<DispatchTable> dispatch_table_;
870 const uint8_t* dispatch_table_snapshot_ = nullptr;
871 intptr_t dispatch_table_snapshot_size_ = 0;
872 ArrayPtr saved_unlinked_calls_;
873 std::shared_ptr<FieldTable> initial_field_table_;
874 uint32_t isolate_group_flags_ = 0;
875
876 NOT_IN_PRECOMPILED(std::unique_ptr<BackgroundCompiler> background_compiler_);
877
878 Mutex symbols_mutex_;
879 Mutex type_canonicalization_mutex_;
880 Mutex type_arguments_canonicalization_mutex_;
881 Mutex subtype_test_cache_mutex_;
882 Mutex megamorphic_table_mutex_;
883 Mutex type_feedback_mutex_;
884 Mutex patchable_call_mutex_;
885 Mutex constant_canonicalization_mutex_;
886 Mutex kernel_data_lib_cache_mutex_;
887 Mutex kernel_data_class_cache_mutex_;
888 Mutex kernel_constants_mutex_;
889
890#if defined(DART_PRECOMPILED_RUNTIME)
891 Mutex unlinked_call_map_mutex_;
892#endif
893
894#if !defined(DART_PRECOMPILED_RUNTIME)
895 Mutex initializer_functions_mutex_;
896#endif // !defined(DART_PRECOMPILED_RUNTIME)
897
898 // Protect access to boxed_field_list_.
899 Mutex field_list_mutex_;
900 // List of fields that became boxed and that trigger deoptimization.
901 GrowableObjectArrayPtr boxed_field_list_;
902
903 // Ensures synchronized access to classes functions, fields and other
904 // program structure elements to accommodate concurrent modification done
905 // by multiple isolates and background compiler.
906 std::unique_ptr<SafepointRwLock> program_lock_;
907
908 // Allow us to ensure the number of active mutators is limited by a maximum.
909 std::unique_ptr<Monitor> active_mutators_monitor_;
910 intptr_t active_mutators_ = 0;
911 intptr_t waiting_mutators_ = 0;
912 intptr_t max_active_mutators_ = 0;
913
914 NOT_IN_PRODUCT(GroupDebugger* debugger_ = nullptr);
915};
916
917// When an isolate sends-and-exits this class represent things that it passed
918// to the beneficiary.
919class Bequest {
920 public:
921 Bequest(PersistentHandle* handle, Dart_Port beneficiary)
922 : handle_(handle), beneficiary_(beneficiary) {}
923 ~Bequest();
924
925 PersistentHandle* handle() { return handle_; }
926 PersistentHandle* TakeHandle() {
927 auto handle = handle_;
928 handle_ = nullptr;
929 return handle;
930 }
931 Dart_Port beneficiary() { return beneficiary_; }
932
933 private:
934 PersistentHandle* handle_;
935 Dart_Port beneficiary_;
936};
937
938class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
939 public:
940 // Keep both these enums in sync with isolate_patch.dart.
941 // The different Isolate API message types.
942 enum LibMsgId {
943 kPauseMsg = 1,
944 kResumeMsg = 2,
945 kPingMsg = 3,
946 kKillMsg = 4,
947 kAddExitMsg = 5,
948 kDelExitMsg = 6,
949 kAddErrorMsg = 7,
950 kDelErrorMsg = 8,
951 kErrorFatalMsg = 9,
952
953 // Internal message ids.
954 kInterruptMsg = 10, // Break in the debugger.
955 kInternalKillMsg = 11, // Like kill, but does not run exit listeners, etc.
956 kDrainServiceExtensionsMsg = 12, // Invoke pending service extensions
957 kCheckForReload = 13, // Participate in other isolate group reload.
958 };
959 // The different Isolate API message priorities for ping and kill messages.
960 enum LibMsgPriority {
961 kImmediateAction = 0,
962 kBeforeNextEventAction = 1,
963 kAsEventAction = 2
964 };
965
966 ~Isolate();
967
968 static inline Isolate* Current() {
969 Thread* thread = Thread::Current();
970 return thread == nullptr ? nullptr : thread->isolate();
971 }
972
973 bool IsScheduled() { return scheduled_mutator_thread() != nullptr; }
974 Thread* scheduled_mutator_thread() const { return scheduled_mutator_thread_; }
975
976 ThreadRegistry* thread_registry() const { return group()->thread_registry(); }
977
978 SafepointHandler* safepoint_handler() const {
979 return group()->safepoint_handler();
980 }
981
982 FieldTable* field_table() const { return field_table_; }
983 void set_field_table(Thread* T, FieldTable* field_table) {
984 delete field_table_;
985 field_table_ = field_table;
986 T->field_table_values_ = field_table->table();
987 }
988
989 IsolateObjectStore* isolate_object_store() const {
990 return isolate_object_store_.get();
991 }
992
993 Dart_MessageNotifyCallback message_notify_callback() const {
994 return message_notify_callback_.load(m: std::memory_order_relaxed);
995 }
996
997 void set_message_notify_callback(Dart_MessageNotifyCallback value) {
998 message_notify_callback_.store(d: value, m: std::memory_order_release);
999 }
1000
1001 void set_on_shutdown_callback(Dart_IsolateShutdownCallback value) {
1002 on_shutdown_callback_ = value;
1003 }
1004 Dart_IsolateShutdownCallback on_shutdown_callback() {
1005 return on_shutdown_callback_;
1006 }
1007 void set_on_cleanup_callback(Dart_IsolateCleanupCallback value) {
1008 on_cleanup_callback_ = value;
1009 }
1010 Dart_IsolateCleanupCallback on_cleanup_callback() {
1011 return on_cleanup_callback_;
1012 }
1013
1014 void bequeath(std::unique_ptr<Bequest> bequest) {
1015 bequest_ = std::move(bequest);
1016 }
1017
1018 IsolateGroupSource* source() const { return isolate_group_->source(); }
1019 IsolateGroup* group() const { return isolate_group_; }
1020
1021 bool HasPendingMessages();
1022
1023 Thread* mutator_thread() const;
1024
1025 const char* name() const { return name_; }
1026 void set_name(const char* name);
1027
1028 int64_t UptimeMicros() const;
1029
1030 Dart_Port main_port() const { return main_port_; }
1031 void set_main_port(Dart_Port port) {
1032 ASSERT(main_port_ == 0); // Only set main port once.
1033 main_port_ = port;
1034 }
1035 Dart_Port origin_id();
1036 void set_origin_id(Dart_Port id);
1037 void set_pause_capability(uint64_t value) { pause_capability_ = value; }
1038 uint64_t pause_capability() const { return pause_capability_; }
1039 void set_terminate_capability(uint64_t value) {
1040 terminate_capability_ = value;
1041 }
1042 uint64_t terminate_capability() const { return terminate_capability_; }
1043
1044 void SendInternalLibMessage(LibMsgId msg_id, uint64_t capability);
1045 static bool SendInternalLibMessage(Dart_Port main_port,
1046 LibMsgId msg_id,
1047 uint64_t capability);
1048
1049 void set_init_callback_data(void* value) { init_callback_data_ = value; }
1050 void* init_callback_data() const { return init_callback_data_; }
1051
1052 void set_finalizers(const GrowableObjectArray& value);
1053 static intptr_t finalizers_offset() {
1054 return OFFSET_OF(Isolate, finalizers_);
1055 }
1056
1057 Dart_EnvironmentCallback environment_callback() const {
1058 return environment_callback_;
1059 }
1060 void set_environment_callback(Dart_EnvironmentCallback value) {
1061 environment_callback_ = value;
1062 }
1063
1064 bool HasDeferredLoadHandler() const {
1065 return group()->deferred_load_handler() != nullptr;
1066 }
1067 ObjectPtr CallDeferredLoadHandler(intptr_t id);
1068
1069 void ScheduleInterrupts(uword interrupt_bits);
1070
1071 const char* MakeRunnable();
1072 void MakeRunnableLocked();
1073 void Run();
1074
1075 MessageHandler* message_handler() const { return message_handler_; }
1076 void set_message_handler(MessageHandler* value) { message_handler_ = value; }
1077
1078 bool is_runnable() const { return LoadIsolateFlagsBit<IsRunnableBit>(); }
1079 void set_is_runnable(bool value) {
1080 UpdateIsolateFlagsBit<IsRunnableBit>(value);
1081#if !defined(PRODUCT)
1082 if (is_runnable()) {
1083 set_last_resume_timestamp();
1084 }
1085#endif
1086 }
1087
1088 Mutex* mutex() { return &mutex_; }
1089
1090#if !defined(PRODUCT)
1091 Debugger* debugger() const { return debugger_; }
1092
1093 // Returns the current SampleBlock used to track CPU profiling samples.
1094 SampleBlock* current_sample_block() const { return current_sample_block_; }
1095 void set_current_sample_block(SampleBlock* block) {
1096 current_sample_block_ = block;
1097 }
1098 void ProcessFreeSampleBlocks(Thread* thread);
1099
1100 // Returns the current SampleBlock used to track Dart allocation samples.
1101 SampleBlock* current_allocation_sample_block() const {
1102 return current_allocation_sample_block_;
1103 }
1104 void set_current_allocation_sample_block(SampleBlock* block) {
1105 current_allocation_sample_block_ = block;
1106 }
1107
1108 bool TakeHasCompletedBlocks() {
1109 return has_completed_blocks_.exchange(arg: 0) != 0;
1110 }
1111 bool TrySetHasCompletedBlocks() {
1112 return has_completed_blocks_.exchange(arg: 1) == 0;
1113 }
1114
1115 void set_single_step(bool value) { single_step_ = value; }
1116 bool single_step() const { return single_step_; }
1117 static intptr_t single_step_offset() {
1118 return OFFSET_OF(Isolate, single_step_);
1119 }
1120
1121 void set_has_resumption_breakpoints(bool value) {
1122 has_resumption_breakpoints_ = value;
1123 }
1124 bool has_resumption_breakpoints() const {
1125 return has_resumption_breakpoints_;
1126 }
1127 static intptr_t has_resumption_breakpoints_offset() {
1128 return OFFSET_OF(Isolate, has_resumption_breakpoints_);
1129 }
1130
1131 bool ResumeRequest() const { return LoadIsolateFlagsBit<ResumeRequestBit>(); }
1132 // Lets the embedder know that a service message resulted in a resume request.
1133 void SetResumeRequest() {
1134 UpdateIsolateFlagsBit<ResumeRequestBit>(value: true);
1135 set_last_resume_timestamp();
1136 }
1137
1138 void set_last_resume_timestamp() {
1139 last_resume_timestamp_ = OS::GetCurrentTimeMillis();
1140 }
1141
1142 int64_t last_resume_timestamp() const { return last_resume_timestamp_; }
1143
1144 // Returns whether the vm service has requested that the debugger
1145 // resume execution.
1146 bool GetAndClearResumeRequest() {
1147 return UpdateIsolateFlagsBit<ResumeRequestBit>(value: false);
1148 }
1149#endif
1150
1151 // Verify that the sender has the capability to pause or terminate the
1152 // isolate.
1153 bool VerifyPauseCapability(const Object& capability) const;
1154 bool VerifyTerminateCapability(const Object& capability) const;
1155
1156 // Returns true if the capability was added or removed from this isolate's
1157 // list of pause events.
1158 bool AddResumeCapability(const Capability& capability);
1159 bool RemoveResumeCapability(const Capability& capability);
1160
1161 void AddExitListener(const SendPort& listener, const Instance& response);
1162 void RemoveExitListener(const SendPort& listener);
1163 void NotifyExitListeners();
1164
1165 void AddErrorListener(const SendPort& listener);
1166 void RemoveErrorListener(const SendPort& listener);
1167 bool NotifyErrorListeners(const char* msg, const char* stacktrace);
1168
1169 bool ErrorsFatal() const { return LoadIsolateFlagsBit<ErrorsFatalBit>(); }
1170 void SetErrorsFatal(bool value) {
1171 UpdateIsolateFlagsBit<ErrorsFatalBit>(value);
1172 }
1173
1174 Random* random() { return &random_; }
1175
1176 Simulator* simulator() const { return simulator_; }
1177 void set_simulator(Simulator* value) { simulator_ = value; }
1178
1179 void IncrementSpawnCount();
1180 void DecrementSpawnCount();
1181 void WaitForOutstandingSpawns();
1182
1183 static void SetCreateGroupCallback(Dart_IsolateGroupCreateCallback cb) {
1184 create_group_callback_ = cb;
1185 }
1186 static Dart_IsolateGroupCreateCallback CreateGroupCallback() {
1187 return create_group_callback_;
1188 }
1189
1190 static void SetInitializeCallback_(Dart_InitializeIsolateCallback cb) {
1191 initialize_callback_ = cb;
1192 }
1193 static Dart_InitializeIsolateCallback InitializeCallback() {
1194 return initialize_callback_;
1195 }
1196
1197 static void SetShutdownCallback(Dart_IsolateShutdownCallback cb) {
1198 shutdown_callback_ = cb;
1199 }
1200 static Dart_IsolateShutdownCallback ShutdownCallback() {
1201 return shutdown_callback_;
1202 }
1203
1204 static void SetCleanupCallback(Dart_IsolateCleanupCallback cb) {
1205 cleanup_callback_ = cb;
1206 }
1207 static Dart_IsolateCleanupCallback CleanupCallback() {
1208 return cleanup_callback_;
1209 }
1210
1211 static void SetGroupCleanupCallback(Dart_IsolateGroupCleanupCallback cb) {
1212 cleanup_group_callback_ = cb;
1213 }
1214 static Dart_IsolateGroupCleanupCallback GroupCleanupCallback() {
1215 return cleanup_group_callback_;
1216 }
1217 static void SetRegisterKernelBlobCallback(
1218 Dart_RegisterKernelBlobCallback cb) {
1219 register_kernel_blob_callback_ = cb;
1220 }
1221 static Dart_RegisterKernelBlobCallback RegisterKernelBlobCallback() {
1222 return register_kernel_blob_callback_;
1223 }
1224 static void SetUnregisterKernelBlobCallback(
1225 Dart_UnregisterKernelBlobCallback cb) {
1226 unregister_kernel_blob_callback_ = cb;
1227 }
1228 static Dart_UnregisterKernelBlobCallback UnregisterKernelBlobCallback() {
1229 return unregister_kernel_blob_callback_;
1230 }
1231
1232#if !defined(PRODUCT)
1233 ObjectIdRing* object_id_ring() const { return object_id_ring_; }
1234 ObjectIdRing* EnsureObjectIdRing();
1235#endif // !defined(PRODUCT)
1236
1237 bool IsDeoptimizing() const { return deopt_context_ != nullptr; }
1238 DeoptContext* deopt_context() const { return deopt_context_; }
1239 void set_deopt_context(DeoptContext* value) {
1240 ASSERT(value == nullptr || deopt_context_ == nullptr);
1241 deopt_context_ = value;
1242 }
1243
1244 FfiCallbackMetadata::Trampoline CreateSyncFfiCallback(
1245 Zone* zone,
1246 const Function& function);
1247 FfiCallbackMetadata::Trampoline CreateAsyncFfiCallback(
1248 Zone* zone,
1249 const Function& send_function,
1250 Dart_Port send_port);
1251 void DeleteFfiCallback(FfiCallbackMetadata::Trampoline callback);
1252
1253 // Visible for testing.
1254 FfiCallbackMetadata::Metadata* ffi_callback_list_head() {
1255 return ffi_callback_list_head_;
1256 }
1257
1258 intptr_t BlockClassFinalization() {
1259 ASSERT(defer_finalization_count_ >= 0);
1260 return defer_finalization_count_++;
1261 }
1262
1263 intptr_t UnblockClassFinalization() {
1264 ASSERT(defer_finalization_count_ > 0);
1265 return defer_finalization_count_--;
1266 }
1267
1268 bool AllowClassFinalization() {
1269 ASSERT(defer_finalization_count_ >= 0);
1270 return defer_finalization_count_ == 0;
1271 }
1272
1273#ifndef PRODUCT
1274 void PrintJSON(JSONStream* stream, bool ref = true);
1275
1276 // Creates an object with the total heap memory usage statistics for this
1277 // isolate.
1278 void PrintMemoryUsageJSON(JSONStream* stream);
1279
1280 void PrintPauseEventJSON(JSONStream* stream);
1281#endif
1282
1283#if !defined(PRODUCT)
1284 VMTagCounters* vm_tag_counters() { return &vm_tag_counters_; }
1285#endif // !defined(PRODUCT)
1286
1287 bool IsPaused() const;
1288
1289#if !defined(PRODUCT)
1290 bool should_pause_post_service_request() const {
1291 return LoadIsolateFlagsBit<ShouldPausePostServiceRequestBit>();
1292 }
1293 void set_should_pause_post_service_request(bool value) {
1294 UpdateIsolateFlagsBit<ShouldPausePostServiceRequestBit>(value);
1295 }
1296#endif // !defined(PRODUCT)
1297
1298 ErrorPtr PausePostRequest();
1299
1300 uword user_tag() const { return user_tag_; }
1301 static intptr_t user_tag_offset() { return OFFSET_OF(Isolate, user_tag_); }
1302 static intptr_t current_tag_offset() {
1303 return OFFSET_OF(Isolate, current_tag_);
1304 }
1305 static intptr_t default_tag_offset() {
1306 return OFFSET_OF(Isolate, default_tag_);
1307 }
1308
1309#if !defined(PRODUCT)
1310#define ISOLATE_METRIC_ACCESSOR(type, variable, name, unit) \
1311 type* Get##variable##Metric() { return &metric_##variable##_; }
1312 ISOLATE_METRIC_LIST(ISOLATE_METRIC_ACCESSOR);
1313#undef ISOLATE_METRIC_ACCESSOR
1314#endif // !defined(PRODUCT)
1315
1316 static intptr_t IsolateListLength();
1317
1318 GrowableObjectArrayPtr tag_table() const { return tag_table_; }
1319 void set_tag_table(const GrowableObjectArray& value);
1320
1321 UserTagPtr current_tag() const { return current_tag_; }
1322 void set_current_tag(const UserTag& tag);
1323
1324 UserTagPtr default_tag() const { return default_tag_; }
1325 void set_default_tag(const UserTag& tag);
1326
1327 // Also sends a paused at exit event over the service protocol.
1328 void SetStickyError(ErrorPtr sticky_error);
1329
1330 ErrorPtr sticky_error() const { return sticky_error_; }
1331 DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError();
1332
1333#ifndef PRODUCT
1334 ErrorPtr InvokePendingServiceExtensionCalls();
1335 void AppendServiceExtensionCall(const Instance& closure,
1336 const String& method_name,
1337 const Array& parameter_keys,
1338 const Array& parameter_values,
1339 const Instance& reply_port,
1340 const Instance& id);
1341 void RegisterServiceExtensionHandler(const String& name,
1342 const Instance& closure);
1343 InstancePtr LookupServiceExtensionHandler(const String& name);
1344#endif
1345
1346 static void VisitIsolates(IsolateVisitor* visitor);
1347
1348#if !defined(PRODUCT)
1349 // Handle service messages until we are told to resume execution.
1350 void PauseEventHandler();
1351#endif
1352
1353 bool is_service_isolate() const {
1354 return LoadIsolateFlagsBit<IsServiceIsolateBit>();
1355 }
1356 void set_is_service_isolate(bool value) {
1357 UpdateIsolateFlagsBit<IsServiceIsolateBit>(value);
1358 }
1359
1360 bool is_kernel_isolate() const {
1361 return LoadIsolateFlagsBit<IsKernelIsolateBit>();
1362 }
1363 void set_is_kernel_isolate(bool value) {
1364 UpdateIsolateFlagsBit<IsKernelIsolateBit>(value);
1365 }
1366
1367 bool is_service_registered() const {
1368 return LoadIsolateFlagsBit<IsServiceRegisteredBit>();
1369 }
1370 void set_is_service_registered(bool value) {
1371 UpdateIsolateFlagsBit<IsServiceRegisteredBit>(value);
1372 }
1373
1374 // Isolate-specific flag handling.
1375 static void FlagsInitialize(Dart_IsolateFlags* api_flags);
1376 void FlagsCopyTo(Dart_IsolateFlags* api_flags) const;
1377 void FlagsCopyFrom(const Dart_IsolateFlags& api_flags);
1378
1379#if defined(DART_PRECOMPILER)
1380#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_field)
1381#else
1382#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_flag)
1383#endif
1384
1385#if !defined(PRODUCT)
1386#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_field)
1387#else
1388#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_flag)
1389#endif
1390
1391#define FLAG_FOR_PRODUCT(from_field, from_flag) (from_field)
1392
1393#define DECLARE_GETTER(when, name, bitname, isolate_flag_name, flag_name) \
1394 bool name() const { \
1395 return FLAG_FOR_##when(LoadIsolateFlagsBit<bitname##Bit>(), flag_name); \
1396 }
1397 BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(DECLARE_GETTER)
1398#undef FLAG_FOR_NONPRODUCT
1399#undef FLAG_FOR_PRECOMPILER
1400#undef FLAG_FOR_PRODUCT
1401#undef DECLARE_GETTER
1402
1403 bool has_attempted_stepping() const {
1404 return LoadIsolateFlagsBit<HasAttemptedSteppingBit>();
1405 }
1406 void set_has_attempted_stepping(bool value) {
1407 UpdateIsolateFlagsBit<HasAttemptedSteppingBit>(value);
1408 }
1409
1410 static void KillAllIsolates(LibMsgId msg_id);
1411 static void KillIfExists(Isolate* isolate, LibMsgId msg_id);
1412
1413 // Lookup an isolate by its main port. Returns nullptr if no matching isolate
1414 // is found.
1415 static Isolate* LookupIsolateByPort(Dart_Port port);
1416
1417 // Lookup an isolate by its main port and return a copy of its name. Returns
1418 // nullptr if not matching isolate is found.
1419 static std::unique_ptr<char[]> LookupIsolateNameByPort(Dart_Port port);
1420
1421 static void DisableIsolateCreation();
1422 static void EnableIsolateCreation();
1423 static bool IsolateCreationEnabled();
1424 static bool IsSystemIsolate(const Isolate* isolate) {
1425 return IsolateGroup::IsSystemIsolateGroup(group: isolate->group());
1426 }
1427 static bool IsVMInternalIsolate(const Isolate* isolate);
1428
1429 HandlerInfoCache* handler_info_cache() { return &handler_info_cache_; }
1430
1431 CatchEntryMovesCache* catch_entry_moves_cache() {
1432 return &catch_entry_moves_cache_;
1433 }
1434
1435 // The weak table used in the snapshot writer for the purpose of fast message
1436 // sending.
1437 WeakTable* forward_table_new() { return forward_table_new_.get(); }
1438 void set_forward_table_new(WeakTable* table);
1439
1440 WeakTable* forward_table_old() { return forward_table_old_.get(); }
1441 void set_forward_table_old(WeakTable* table);
1442
1443 void RememberLiveTemporaries();
1444 void DeferredMarkLiveTemporaries();
1445
1446 std::unique_ptr<VirtualMemory> TakeRegexpBacktrackStack() {
1447 return std::move(regexp_backtracking_stack_cache_);
1448 }
1449
1450 void CacheRegexpBacktrackStack(std::unique_ptr<VirtualMemory> stack) {
1451 regexp_backtracking_stack_cache_ = std::move(stack);
1452 }
1453
1454 void init_loaded_prefixes_set_storage();
1455 bool IsPrefixLoaded(const LibraryPrefix& prefix) const;
1456 void SetPrefixIsLoaded(const LibraryPrefix& prefix);
1457
1458 MallocGrowableArray<ObjectPtr>* pointers_to_verify_at_exit() {
1459 return &pointers_to_verify_at_exit_;
1460 }
1461
1462 private:
1463 friend class Dart; // Init, InitOnce, Shutdown.
1464 friend class IsolateKillerVisitor; // Kill().
1465 friend Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* g,
1466 const char* n,
1467 char** e);
1468
1469 Isolate(IsolateGroup* group, const Dart_IsolateFlags& api_flags);
1470
1471 static void InitVM();
1472 static Isolate* InitIsolate(const char* name_prefix,
1473 IsolateGroup* isolate_group,
1474 const Dart_IsolateFlags& api_flags,
1475 bool is_vm_isolate = false);
1476
1477 // The isolate_creation_monitor_ should be held when calling Kill().
1478 void KillLocked(LibMsgId msg_id);
1479
1480 void Shutdown();
1481 void RunAndCleanupFinalizersOnShutdown();
1482 void LowLevelShutdown();
1483
1484 // Unregister the [isolate] from the thread, remove it from the isolate group,
1485 // invoke the cleanup function (if any), delete the isolate and possibly
1486 // delete the isolate group (if it's the last isolate in the group).
1487 static void LowLevelCleanup(Isolate* isolate);
1488
1489 void BuildName(const char* name_prefix);
1490
1491 void ProfileIdle();
1492
1493 // Visit all object pointers. Caller must ensure concurrent sweeper is not
1494 // running, and the visitor must not allocate.
1495 void VisitObjectPointers(ObjectPointerVisitor* visitor,
1496 ValidationPolicy validate_frames);
1497 void VisitStackPointers(ObjectPointerVisitor* visitor,
1498 ValidationPolicy validate_frames);
1499
1500 void set_user_tag(uword tag) { user_tag_ = tag; }
1501
1502 void set_is_system_isolate(bool is_system_isolate) {
1503 is_system_isolate_ = is_system_isolate;
1504 }
1505
1506#if !defined(PRODUCT)
1507 GrowableObjectArrayPtr GetAndClearPendingServiceExtensionCalls();
1508 GrowableObjectArrayPtr pending_service_extension_calls() const {
1509 return pending_service_extension_calls_;
1510 }
1511 void set_pending_service_extension_calls(const GrowableObjectArray& value);
1512 GrowableObjectArrayPtr registered_service_extension_handlers() const {
1513 return registered_service_extension_handlers_;
1514 }
1515 void set_registered_service_extension_handlers(
1516 const GrowableObjectArray& value);
1517#endif // !defined(PRODUCT)
1518
1519 // DEPRECATED: Use Thread's methods instead. During migration, these default
1520 // to using the mutator thread (which must also be the current thread).
1521 Zone* current_zone() const {
1522 ASSERT(Thread::Current() == mutator_thread());
1523 return mutator_thread()->zone();
1524 }
1525
1526 // Accessed from generated code.
1527 // ** This block of fields must come first! **
1528 // For AOT cross-compilation, we rely on these members having the same offsets
1529 // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
1530 // We use only word-sized fields to avoid differences in struct packing on the
1531 // different architectures. See also CheckOffsets in dart.cc.
1532 uword user_tag_ = 0;
1533 UserTagPtr current_tag_;
1534 UserTagPtr default_tag_;
1535 FieldTable* field_table_ = nullptr;
1536 // Used to clear out `UntaggedFinalizerBase::isolate_` pointers on isolate
1537 // shutdown to prevent usage of dangling pointers.
1538 GrowableObjectArrayPtr finalizers_;
1539 bool single_step_ = false;
1540 bool has_resumption_breakpoints_ = false;
1541 bool is_system_isolate_ = false;
1542 // End accessed from generated code.
1543
1544 IsolateGroup* isolate_group_;
1545 IdleTimeHandler idle_time_handler_;
1546 std::unique_ptr<IsolateObjectStore> isolate_object_store_;
1547
1548#define ISOLATE_FLAG_BITS(V) \
1549 V(ErrorsFatal) \
1550 V(IsRunnable) \
1551 V(IsServiceIsolate) \
1552 V(IsKernelIsolate) \
1553 V(ResumeRequest) \
1554 V(HasAttemptedStepping) \
1555 V(ShouldPausePostServiceRequest) \
1556 V(CopyParentCode) \
1557 V(IsSystemIsolate) \
1558 V(IsServiceRegistered)
1559
1560 // Isolate specific flags.
1561 enum FlagBits {
1562#define DECLARE_BIT(Name) k##Name##Bit,
1563 ISOLATE_FLAG_BITS(DECLARE_BIT)
1564#undef DECLARE_BIT
1565 };
1566
1567#define DECLARE_BITFIELD(Name) \
1568 class Name##Bit : public BitField<uint32_t, bool, k##Name##Bit, 1> {};
1569 ISOLATE_FLAG_BITS(DECLARE_BITFIELD)
1570#undef DECLARE_BITFIELD
1571
1572 template <class T>
1573 bool UpdateIsolateFlagsBit(bool value) {
1574 return T::decode(value ? isolate_flags_.fetch_or(T::encode(true),
1575 std::memory_order_relaxed)
1576 : isolate_flags_.fetch_and(
1577 ~T::encode(true), std::memory_order_relaxed));
1578 }
1579 template <class T>
1580 bool LoadIsolateFlagsBit() const {
1581 return T::decode(isolate_flags_.load(m: std::memory_order_relaxed));
1582 }
1583 std::atomic<uint32_t> isolate_flags_;
1584
1585// Fields that aren't needed in a product build go here with boolean flags at
1586// the top.
1587#if !defined(PRODUCT)
1588 Debugger* debugger_ = nullptr;
1589
1590 // SampleBlock containing CPU profiling samples.
1591 RelaxedAtomic<SampleBlock*> current_sample_block_ = nullptr;
1592
1593 // SampleBlock containing Dart allocation profiling samples.
1594 RelaxedAtomic<SampleBlock*> current_allocation_sample_block_ = nullptr;
1595
1596 RelaxedAtomic<uword> has_completed_blocks_ = {0};
1597
1598 int64_t last_resume_timestamp_;
1599
1600 VMTagCounters vm_tag_counters_;
1601
1602 // We use 6 list entries for each pending service extension calls.
1603 enum {kPendingHandlerIndex = 0, kPendingMethodNameIndex, kPendingKeysIndex,
1604 kPendingValuesIndex, kPendingReplyPortIndex, kPendingIdIndex,
1605 kPendingEntrySize};
1606 GrowableObjectArrayPtr pending_service_extension_calls_;
1607
1608 // We use 2 list entries for each registered extension handler.
1609 enum {kRegisteredNameIndex = 0, kRegisteredHandlerIndex,
1610 kRegisteredEntrySize};
1611 GrowableObjectArrayPtr registered_service_extension_handlers_;
1612
1613 // Used to wake the isolate when it is in the pause event loop.
1614 Monitor* pause_loop_monitor_ = nullptr;
1615
1616#define ISOLATE_METRIC_VARIABLE(type, variable, name, unit) \
1617 type metric_##variable##_;
1618 ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
1619#undef ISOLATE_METRIC_VARIABLE
1620
1621 // Ring buffer of objects assigned an id.
1622 ObjectIdRing* object_id_ring_ = nullptr;
1623#endif // !defined(PRODUCT)
1624
1625 // All other fields go here.
1626 int64_t start_time_micros_;
1627 std::atomic<Dart_MessageNotifyCallback> message_notify_callback_;
1628 Dart_IsolateShutdownCallback on_shutdown_callback_ = nullptr;
1629 Dart_IsolateCleanupCallback on_cleanup_callback_ = nullptr;
1630 char* name_ = nullptr;
1631 Dart_Port main_port_ = 0;
1632 // Isolates created by Isolate.spawn have the same origin id.
1633 Dart_Port origin_id_ = 0;
1634 Mutex origin_id_mutex_;
1635 uint64_t pause_capability_ = 0;
1636 uint64_t terminate_capability_ = 0;
1637 void* init_callback_data_ = nullptr;
1638 Dart_EnvironmentCallback environment_callback_ = nullptr;
1639 Random random_;
1640 Simulator* simulator_ = nullptr;
1641 Mutex mutex_; // Protects compiler stats.
1642 MessageHandler* message_handler_ = nullptr;
1643 intptr_t defer_finalization_count_ = 0;
1644 DeoptContext* deopt_context_ = nullptr;
1645 FfiCallbackMetadata::Metadata* ffi_callback_list_head_ = nullptr;
1646
1647 GrowableObjectArrayPtr tag_table_;
1648
1649 ErrorPtr sticky_error_;
1650
1651 std::unique_ptr<Bequest> bequest_;
1652 Dart_Port beneficiary_ = 0;
1653
1654 // This guards spawn_count_. An isolate cannot complete shutdown and be
1655 // destroyed while there are child isolates in the midst of a spawn.
1656 Monitor spawn_count_monitor_;
1657 intptr_t spawn_count_ = 0;
1658
1659 HandlerInfoCache handler_info_cache_;
1660 CatchEntryMovesCache catch_entry_moves_cache_;
1661
1662 DispatchTable* dispatch_table_ = nullptr;
1663
1664 // Used during message sending of messages between isolates.
1665 std::unique_ptr<WeakTable> forward_table_new_;
1666 std::unique_ptr<WeakTable> forward_table_old_;
1667
1668 // Signals whether the isolate can receive messages (e.g. KillAllIsolates can
1669 // send a kill message).
1670 // This is protected by [isolate_creation_monitor_].
1671 bool accepts_messages_ = false;
1672
1673 std::unique_ptr<VirtualMemory> regexp_backtracking_stack_cache_ = nullptr;
1674
1675 intptr_t wake_pause_event_handler_count_;
1676
1677 static Dart_IsolateGroupCreateCallback create_group_callback_;
1678 static Dart_InitializeIsolateCallback initialize_callback_;
1679 static Dart_IsolateShutdownCallback shutdown_callback_;
1680 static Dart_IsolateCleanupCallback cleanup_callback_;
1681 static Dart_IsolateGroupCleanupCallback cleanup_group_callback_;
1682 static Dart_RegisterKernelBlobCallback register_kernel_blob_callback_;
1683 static Dart_UnregisterKernelBlobCallback unregister_kernel_blob_callback_;
1684
1685#if !defined(PRODUCT)
1686 static void WakePauseEventHandler(Dart_Isolate isolate);
1687#endif
1688
1689 // Manage list of existing isolates.
1690 static bool TryMarkIsolateReady(Isolate* isolate);
1691 static void UnMarkIsolateReady(Isolate* isolate);
1692 static void MaybeNotifyVMShutdown();
1693 bool AcceptsMessagesLocked() {
1694 ASSERT(isolate_creation_monitor_->IsOwnedByCurrentThread());
1695 return accepts_messages_;
1696 }
1697
1698 // This monitor protects [creation_enabled_].
1699 static Monitor* isolate_creation_monitor_;
1700 static bool creation_enabled_;
1701
1702 ArrayPtr loaded_prefixes_set_storage_;
1703
1704 MallocGrowableArray<ObjectPtr> pointers_to_verify_at_exit_;
1705
1706#define REUSABLE_FRIEND_DECLARATION(name) \
1707 friend class Reusable##name##HandleScope;
1708 REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
1709#undef REUSABLE_FRIEND_DECLARATION
1710
1711 friend class Become; // VisitObjectPointers
1712 friend class GCCompactor; // VisitObjectPointers
1713 friend class GCMarker; // VisitObjectPointers
1714 friend class SafepointHandler;
1715 friend class ObjectGraph; // VisitObjectPointers
1716 friend class HeapSnapshotWriter; // VisitObjectPointers
1717 friend class Scavenger; // VisitObjectPointers
1718 friend class HeapIterationScope; // VisitObjectPointers
1719 friend class ServiceIsolate;
1720 friend class Thread;
1721 friend class Timeline;
1722 friend class IsolateGroup; // reload_context_
1723
1724 DISALLOW_COPY_AND_ASSIGN(Isolate);
1725};
1726
1727// When we need to execute code in an isolate, we use the
1728// StartIsolateScope.
1729class StartIsolateScope {
1730 public:
1731 explicit StartIsolateScope(Isolate* new_isolate)
1732 : new_isolate_(new_isolate), saved_isolate_(Isolate::Current()) {
1733 if (new_isolate_ == nullptr) {
1734 ASSERT(Isolate::Current() == nullptr);
1735 // Do nothing.
1736 return;
1737 }
1738 if (saved_isolate_ != new_isolate_) {
1739 ASSERT(Isolate::Current() == nullptr);
1740 Thread::EnterIsolate(isolate: new_isolate_);
1741 // Ensure this is not a nested 'isolate enter' with prior state.
1742 ASSERT(Thread::Current()->top_exit_frame_info() == 0);
1743 }
1744 }
1745
1746 ~StartIsolateScope() {
1747 if (new_isolate_ == nullptr) {
1748 ASSERT(Isolate::Current() == nullptr);
1749 // Do nothing.
1750 return;
1751 }
1752 if (saved_isolate_ != new_isolate_) {
1753 ASSERT(saved_isolate_ == nullptr);
1754 // ASSERT that we have bottomed out of all Dart invocations.
1755 ASSERT(Thread::Current()->top_exit_frame_info() == 0);
1756 Thread::ExitIsolate();
1757 }
1758 }
1759
1760 private:
1761 Isolate* new_isolate_;
1762 Isolate* saved_isolate_;
1763
1764 DISALLOW_COPY_AND_ASSIGN(StartIsolateScope);
1765};
1766
1767class EnterIsolateGroupScope {
1768 public:
1769 explicit EnterIsolateGroupScope(IsolateGroup* isolate_group)
1770 : isolate_group_(isolate_group) {
1771 ASSERT(IsolateGroup::Current() == nullptr);
1772 const bool result = Thread::EnterIsolateGroupAsHelper(
1773 isolate_group: isolate_group_, kind: Thread::kUnknownTask, /*bypass_safepoint=*/bypass_safepoint: false);
1774 ASSERT(result);
1775 }
1776
1777 ~EnterIsolateGroupScope() {
1778 Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/bypass_safepoint: false);
1779 }
1780
1781 private:
1782 IsolateGroup* isolate_group_;
1783
1784 DISALLOW_COPY_AND_ASSIGN(EnterIsolateGroupScope);
1785};
1786
1787// Ensure that isolate is not available for the duration of this scope.
1788//
1789// This can be used in code (e.g. GC, Kernel Loader, Compiler) that should not
1790// operate on an individual isolate.
1791class NoActiveIsolateScope : public StackResource {
1792 public:
1793 NoActiveIsolateScope() : NoActiveIsolateScope(Thread::Current()) {}
1794 explicit NoActiveIsolateScope(Thread* thread)
1795 : StackResource(thread), thread_(thread) {
1796 outer_ = thread_->no_active_isolate_scope_;
1797 saved_isolate_ = thread_->isolate_;
1798
1799 thread_->no_active_isolate_scope_ = this;
1800 thread_->isolate_ = nullptr;
1801 }
1802 ~NoActiveIsolateScope() {
1803 ASSERT(thread_->isolate_ == nullptr);
1804 thread_->isolate_ = saved_isolate_;
1805 thread_->no_active_isolate_scope_ = outer_;
1806 }
1807
1808 private:
1809 friend class ActiveIsolateScope;
1810
1811 Thread* thread_;
1812 Isolate* saved_isolate_;
1813 NoActiveIsolateScope* outer_;
1814};
1815
1816class ActiveIsolateScope : public StackResource {
1817 public:
1818 explicit ActiveIsolateScope(Thread* thread)
1819 : ActiveIsolateScope(thread,
1820 thread->no_active_isolate_scope_->saved_isolate_) {}
1821
1822 ActiveIsolateScope(Thread* thread, Isolate* isolate)
1823 : StackResource(thread), thread_(thread) {
1824 RELEASE_ASSERT(thread->isolate() == nullptr);
1825 thread_->isolate_ = isolate;
1826 }
1827 ~ActiveIsolateScope() {
1828 ASSERT(thread_->isolate_ != nullptr);
1829 thread_->isolate_ = nullptr;
1830 }
1831
1832 private:
1833 Thread* thread_;
1834};
1835
1836} // namespace dart
1837
1838#endif // RUNTIME_VM_ISOLATE_H_
1839

source code of flutter_engine/third_party/dart/runtime/vm/isolate.h