Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
pointer_block.cc
Go to the documentation of this file.
1// Copyright (c) 2012, 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
6
7#include "platform/assert.h"
8#include "vm/lockers.h"
9#include "vm/runtime_entry.h"
10
11namespace dart {
12
13DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) {
15}
17
18DEFINE_LEAF_RUNTIME_ENTRY(void, MarkingStackBlockProcess, 1, Thread* thread) {
20}
22
23template <int BlockSize>
24typename BlockStack<BlockSize>::List* BlockStack<BlockSize>::global_empty_ =
25 nullptr;
26template <int BlockSize>
28
29template <int BlockSize>
31 global_empty_ = new List();
32 if (global_mutex_ == nullptr) {
33 global_mutex_ = new Mutex();
34 }
35}
36
37template <int BlockSize>
39 delete global_empty_;
40 global_empty_ = nullptr;
41}
42
43template <int BlockSize>
45
46template <int BlockSize>
50
51template <int BlockSize>
53 MonitorLocker local_mutex_locker(&monitor_);
54 {
55 // Empty all blocks and move them to the global cache.
56 MutexLocker global_mutex_locker(global_mutex_);
57 while (!full_.IsEmpty()) {
58 Block* block = full_.Pop();
59 block->Reset();
60 global_empty_->Push(block);
61 }
62 while (!partial_.IsEmpty()) {
63 Block* block = partial_.Pop();
64 block->Reset();
65 global_empty_->Push(block);
66 }
67 TrimGlobalEmpty();
68 }
69}
70
71template <int BlockSize>
73 MonitorLocker ml(&monitor_);
74 while (!partial_.IsEmpty()) {
75 full_.Push(partial_.Pop());
76 }
77 return full_.PopAll();
78}
79
80template <int BlockSize>
82 while (block != nullptr) {
83 Block* next = block->next();
84 block->set_next(nullptr);
85 PushBlockImpl(block);
86 block = next;
87 }
88}
89
90template <int BlockSize>
92 ASSERT(block->next() == nullptr); // Should be just a single block.
93 if (block->IsFull()) {
94 MonitorLocker ml(&monitor_);
95 bool was_empty = IsEmptyLocked();
96 full_.Push(block);
97 if (was_empty) ml.Notify();
98 } else if (block->IsEmpty()) {
99 MutexLocker ml(global_mutex_);
100 global_empty_->Push(block);
101 TrimGlobalEmpty();
102 } else {
103 MonitorLocker ml(&monitor_);
104 bool was_empty = IsEmptyLocked();
105 partial_.Push(block);
106 if (was_empty) ml.Notify();
108}
109
110template <int BlockSize>
113 bool abort) {
114 MonitorLocker ml(&monitor_);
115 if (num_busy->fetch_sub(1u) == 1 /* 1 is before subtraction */) {
116 // This is the last worker, wake the others now that we know no further work
117 // will come.
118 ml.NotifyAll();
119 return nullptr;
120 }
121 if (abort) {
122 return nullptr;
124 for (;;) {
125 if (!full_.IsEmpty()) {
126 num_busy->fetch_add(1u);
127 return full_.Pop();
128 }
129 if (!partial_.IsEmpty()) {
130 num_busy->fetch_add(1u);
131 return partial_.Pop();
132 }
133 ml.Wait();
134 if (num_busy->load() == 0) {
135 return nullptr;
137 }
138}
140template <int Size>
142 // Generated code appends to store buffers; tell MemorySanitizer.
143 MSAN_UNPOISON(this, sizeof(*this));
144 visitor->VisitPointers(&pointers_[0], top_);
145}
146
149 if ((policy == kCheckThreshold) && Overflowed()) {
151 Thread* thread = Thread::Current();
152 // Sanity check: it makes no sense to schedule the GC in another isolate
153 // group.
154 // (If Isolate ever gets multiple store buffers, we should avoid this
155 // coupling by passing in an explicit callback+parameter at construction.)
156 ASSERT(thread->isolate_group()->store_buffer() == this);
158 }
159}
160
161template <int BlockSize>
164 {
165 MonitorLocker ml(&monitor_);
166 if (!partial_.IsEmpty()) {
167 return partial_.Pop();
168 }
169 }
170 return PopEmptyBlock();
171}
172
173template <int BlockSize>
175 {
176 MutexLocker ml(global_mutex_);
177 if (!global_empty_->IsEmpty()) {
178 return global_empty_->Pop();
179 }
180 }
181 return new Block();
182}
183
184template <int BlockSize>
187 MonitorLocker ml(&monitor_);
188 if (!full_.IsEmpty()) {
189 return full_.Pop();
190 } else if (!partial_.IsEmpty()) {
191 return partial_.Pop();
192 } else {
193 return nullptr;
194 }
195}
196
197template <int BlockSize>
199 MonitorLocker ml(&monitor_);
200 return IsEmptyLocked();
201}
202
203template <int BlockSize>
205 return full_.IsEmpty() && partial_.IsEmpty();
206}
207
208template <int BlockSize>
210 while (!IsEmpty()) {
211 delete Pop();
212 }
213}
214
215template <int BlockSize>
217 Block* result = head_;
218 head_ = head_->next_;
219 --length_;
220 result->next_ = nullptr;
221 return result;
222}
223
224template <int BlockSize>
226 Block* result = head_;
227 head_ = nullptr;
228 length_ = 0;
229 return result;
230}
231
232template <int BlockSize>
234 ASSERT(block->next_ == nullptr);
235 block->next_ = head_;
236 head_ = block;
237 ++length_;
238}
239
242 return (full_.length() + partial_.length()) > kMaxNonEmpty;
243}
244
246 ASSERT(Thread::Current()->OwnsGCSafepoint()); // No lock needed.
247 return full_.length() + partial_.length();
248}
249
250template <int BlockSize>
252 for (Block* block = full_.Peek(); block != nullptr; block = block->next()) {
253 block->VisitObjectPointers(visitor);
254 }
255 for (Block* block = partial_.Peek(); block != nullptr;
256 block = block->next()) {
257 block->VisitObjectPointers(visitor);
258 }
259}
260
261template <int BlockSize>
268
271
272} // namespace dart
static float next(float f)
SkBlockAllocator::Block Block
SkIDChangeListener::List List
#define DEBUG_ASSERT(cond)
Definition assert.h:321
intptr_t length() const
static void TrimGlobalEmpty()
Block * PopNonFullBlock()
static Mutex * global_mutex_
Block * WaitForWork(RelaxedAtomic< uintptr_t > *num_busy, bool abort)
static List * global_empty_
void PushAll(Block *blocks)
void VisitObjectPointers(ObjectPointerVisitor *visitor)
static constexpr intptr_t kMaxGlobalEmpty
Block * PopEmptyBlock()
void PushBlockImpl(Block *block)
Block * PopNonEmptyBlock()
static void Init()
static void Cleanup()
StoreBuffer * store_buffer() const
Definition isolate.h:504
bool IsOwnedByCurrentThread() const
Definition os_thread.h:401
virtual void VisitPointers(ObjectPtr *first, ObjectPtr *last)=0
PointerBlock< Size > * next() const
bool IsFull() const
void set_next(PointerBlock< Size > *next)
void VisitObjectPointers(ObjectPointerVisitor *visitor)
bool IsEmpty() const
T load(std::memory_order order=std::memory_order_relaxed) const
Definition atomic.h:21
T fetch_add(T arg, std::memory_order order=std::memory_order_relaxed)
Definition atomic.h:35
T fetch_sub(T arg, std::memory_order order=std::memory_order_relaxed)
Definition atomic.h:38
void PushBlock(Block *block, ThresholdPolicy policy)
void ScheduleInterrupts(uword interrupt_bits)
Definition thread.cc:705
void MarkingStackBlockProcess()
Definition thread.cc:816
static Thread * Current()
Definition thread.h:361
void StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy)
Definition thread.cc:786
IsolateGroup * isolate_group() const
Definition thread.h:540
#define ASSERT(E)
GAsyncResult * result
#define MSAN_UNPOISON(ptr, len)
#define END_LEAF_RUNTIME_ENTRY
#define DEFINE_LEAF_RUNTIME_ENTRY(type, name, argument_count,...)