1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_SAFEPOINT_H_ 6 #define V8_HEAP_SAFEPOINT_H_ 7 8 #include "src/base/platform/condition-variable.h" 9 #include "src/base/platform/mutex.h" 10 #include "src/handles/persistent-handles.h" 11 #include "src/heap/local-heap.h" 12 #include "src/objects/visitors.h" 13 14 namespace v8 { 15 namespace internal { 16 17 class Heap; 18 class LocalHeap; 19 class RootVisitor; 20 21 // Used to bring all background threads with heap access to a safepoint such 22 // that e.g. a garbage collection can be performed. 23 class GlobalSafepoint { 24 public: 25 explicit GlobalSafepoint(Heap* heap); 26 27 // Enter the safepoint from a thread 28 void EnterFromThread(LocalHeap* local_heap); 29 30 V8_EXPORT_PRIVATE bool ContainsLocalHeap(LocalHeap* local_heap); 31 V8_EXPORT_PRIVATE bool ContainsAnyLocalHeap(); 32 33 // Iterate handles in local heaps 34 void Iterate(RootVisitor* visitor); 35 36 // Iterate local heaps 37 template <typename Callback> IterateLocalHeaps(Callback callback)38 void IterateLocalHeaps(Callback callback) { 39 DCHECK(IsActive()); 40 for (LocalHeap* current = local_heaps_head_; current; 41 current = current->next_) { 42 callback(current); 43 } 44 } 45 IsActive()46 bool IsActive() { return active_safepoint_scopes_ > 0; } 47 48 private: 49 class Barrier { 50 base::Mutex mutex_; 51 base::ConditionVariable cond_; 52 bool armed_; 53 54 public: Barrier()55 Barrier() : armed_(false) {} 56 57 void Arm(); 58 void Disarm(); 59 void Wait(); 60 }; 61 62 void EnterSafepointScope(); 63 void LeaveSafepointScope(); 64 65 template <typename Callback> AddLocalHeap(LocalHeap * local_heap,Callback callback)66 void AddLocalHeap(LocalHeap* local_heap, Callback callback) { 67 // Safepoint holds this lock in order to stop threads from starting or 68 // stopping. 69 base::MutexGuard guard(&local_heaps_mutex_); 70 71 // Additional code protected from safepoint 72 callback(); 73 74 // Add list to doubly-linked list 75 if (local_heaps_head_) local_heaps_head_->prev_ = local_heap; 76 local_heap->prev_ = nullptr; 77 local_heap->next_ = local_heaps_head_; 78 local_heaps_head_ = local_heap; 79 } 80 81 template <typename Callback> RemoveLocalHeap(LocalHeap * local_heap,Callback callback)82 void RemoveLocalHeap(LocalHeap* local_heap, Callback callback) { 83 base::MutexGuard guard(&local_heaps_mutex_); 84 85 // Additional code protected from safepoint 86 callback(); 87 88 // Remove list from doubly-linked list 89 if (local_heap->next_) local_heap->next_->prev_ = local_heap->prev_; 90 if (local_heap->prev_) 91 local_heap->prev_->next_ = local_heap->next_; 92 else 93 local_heaps_head_ = local_heap->next_; 94 } 95 96 Barrier barrier_; 97 Heap* heap_; 98 99 base::Mutex local_heaps_mutex_; 100 LocalHeap* local_heaps_head_; 101 102 int active_safepoint_scopes_; 103 104 LocalHeap* local_heap_of_this_thread_; 105 106 friend class SafepointScope; 107 friend class LocalHeap; 108 friend class PersistentHandles; 109 }; 110 111 class SafepointScope { 112 public: 113 V8_EXPORT_PRIVATE explicit SafepointScope(Heap* heap); 114 V8_EXPORT_PRIVATE ~SafepointScope(); 115 116 private: 117 GlobalSafepoint* safepoint_; 118 }; 119 120 } // namespace internal 121 } // namespace v8 122 123 #endif // V8_HEAP_SAFEPOINT_H_ 124