• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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