Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(634)

Side by Side Diff: src/heap/sequential-marking-deque.h

Issue 2810893002: [heap] Implement simple concurrent marking deque. (Closed)
Patch Set: revert flags Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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_SEQUENTIAL_MARKING_DEQUE_
6 #define V8_HEAP_SEQUENTIAL_MARKING_DEQUE_
7
8 #include <deque>
9
10 #include "src/base/platform/mutex.h"
11 #include "src/base/platform/platform.h"
12 #include "src/cancelable-task.h"
13
14 namespace v8 {
15 namespace internal {
16
17 class Heap;
18 class Isolate;
19 class HeapObject;
20
21 // ----------------------------------------------------------------------------
22 // Marking deque for tracing live objects.
23 class SequentialMarkingDeque {
24 public:
25 explicit SequentialMarkingDeque(Heap* heap)
26 : backing_store_(nullptr),
27 backing_store_committed_size_(0),
28 array_(nullptr),
29 top_(0),
30 bottom_(0),
31 mask_(0),
32 overflowed_(false),
33 in_use_(false),
34 uncommit_task_pending_(false),
35 heap_(heap) {}
36
37 void SetUp();
38 void TearDown();
39
40 // Ensures that the marking deque is committed and will stay committed until
41 // StopUsing() is called.
42 void StartUsing();
43 void StopUsing();
44 void Clear();
45
46 inline bool IsFull() { return ((top_ + 1) & mask_) == bottom_; }
47
48 inline bool IsEmpty() { return top_ == bottom_; }
49
50 int Size() { return (top_ + mask_ + 1 - bottom_) & mask_; }
51
52 bool overflowed() const { return overflowed_; }
53
54 void ClearOverflowed() { overflowed_ = false; }
55
56 void SetOverflowed() { overflowed_ = true; }
57
58 // Push the object on the marking stack if there is room, otherwise mark the
59 // deque as overflowed and wait for a rescan of the heap.
60 INLINE(bool Push(HeapObject* object)) {
61 if (IsFull()) {
62 SetOverflowed();
63 return false;
64 } else {
65 array_[top_] = object;
66 top_ = ((top_ + 1) & mask_);
67 return true;
68 }
69 }
70
71 INLINE(HeapObject* Pop()) {
72 DCHECK(!IsEmpty());
73 top_ = ((top_ - 1) & mask_);
74 HeapObject* object = array_[top_];
75 return object;
76 }
77
78 // Unshift the object into the marking stack if there is room, otherwise mark
79 // the deque as overflowed and wait for a rescan of the heap.
80 INLINE(bool Unshift(HeapObject* object)) {
81 if (IsFull()) {
82 SetOverflowed();
83 return false;
84 } else {
85 bottom_ = ((bottom_ - 1) & mask_);
86 array_[bottom_] = object;
87 return true;
88 }
89 }
90
91 // Calls the specified callback on each element of the deque and replaces
92 // the element with the result of the callback. If the callback returns
93 // nullptr then the element is removed from the deque.
94 // The callback must accept HeapObject* and return HeapObject*.
95 template <typename Callback>
96 void Update(Callback callback) {
97 int i = bottom_;
98 int new_top = bottom_;
99 while (i != top_) {
100 HeapObject* object = callback(array_[i]);
101 if (object) {
102 array_[new_top] = object;
103 new_top = (new_top + 1) & mask_;
104 }
105 i = (i + 1) & mask_;
106 }
107 top_ = new_top;
108 }
109
110 private:
111 // This task uncommits the marking_deque backing store if
112 // markin_deque->in_use_ is false.
113 class UncommitTask : public CancelableTask {
114 public:
115 explicit UncommitTask(Isolate* isolate,
116 SequentialMarkingDeque* marking_deque)
117 : CancelableTask(isolate), marking_deque_(marking_deque) {}
118
119 private:
120 // CancelableTask override.
121 void RunInternal() override {
122 base::LockGuard<base::Mutex> guard(&marking_deque_->mutex_);
123 if (!marking_deque_->in_use_) {
124 marking_deque_->Uncommit();
125 }
126 marking_deque_->uncommit_task_pending_ = false;
127 }
128
129 SequentialMarkingDeque* marking_deque_;
130 DISALLOW_COPY_AND_ASSIGN(UncommitTask);
131 };
132
133 static const size_t kMaxSize = 4 * MB;
134 static const size_t kMinSize = 256 * KB;
135
136 // Must be called with mutex lock.
137 void EnsureCommitted();
138
139 // Must be called with mutex lock.
140 void Uncommit();
141
142 // Must be called with mutex lock.
143 void StartUncommitTask();
144
145 base::Mutex mutex_;
146
147 base::VirtualMemory* backing_store_;
148 size_t backing_store_committed_size_;
149 HeapObject** array_;
150 // array_[(top - 1) & mask_] is the top element in the deque. The Deque is
151 // empty when top_ == bottom_. It is full when top_ + 1 == bottom
152 // (mod mask + 1).
153 int top_;
154 int bottom_;
155 int mask_;
156 bool overflowed_;
157 // in_use_ == true after taking mutex lock implies that the marking deque is
158 // committed and will stay committed at least until in_use_ == false.
159 bool in_use_;
160 bool uncommit_task_pending_;
161 Heap* heap_;
162
163 DISALLOW_COPY_AND_ASSIGN(SequentialMarkingDeque);
164 };
165
166 } // namespace internal
167 } // namespace v8
168
169 #endif // V8_SEQUENTIAL_MARKING_DEQUE_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698