Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
19 OldMarkingStackBlockProcess,
20 1,
21 Thread* thread) {
23}
25
27 NewMarkingStackBlockProcess,
28 1,
29 Thread* thread) {
31}
33
34template <int BlockSize>
36 nullptr;
37template <int BlockSize>
39
40template <int BlockSize>
42 global_empty_ = new List();
43 if (global_mutex_ == nullptr) {
44 global_mutex_ = new Mutex();
45 }
46}
47
48template <int BlockSize>
50 delete global_empty_;
51 global_empty_ = nullptr;
52}
53
54template <int BlockSize>
56
57template <int BlockSize>
59 Reset();
60}
61
62template <int BlockSize>
64 MonitorLocker local_mutex_locker(&monitor_);
65 {
66 // Empty all blocks and move them to the global cache.
67 MutexLocker global_mutex_locker(global_mutex_);
68 while (!full_.IsEmpty()) {
69 Block* block = full_.Pop();
70 block->Reset();
71 global_empty_->Push(block);
72 }
73 while (!partial_.IsEmpty()) {
74 Block* block = partial_.Pop();
75 block->Reset();
76 global_empty_->Push(block);
77 }
78 TrimGlobalEmpty();
79 }
80}
81
82template <int BlockSize>
84 MonitorLocker ml(&monitor_);
85 while (!partial_.IsEmpty()) {
86 full_.Push(partial_.Pop());
87 }
88 return full_.PopAll();
89}
90
91template <int BlockSize>
93 while (block != nullptr) {
94 Block* next = block->next();
95 block->set_next(nullptr);
96 PushBlockImpl(block);
97 block = next;
98 }
99}
100
101template <int BlockSize>
103 ASSERT(block->next() == nullptr); // Should be just a single block.
104 if (block->IsFull()) {
105 MonitorLocker ml(&monitor_);
106 bool was_empty = IsEmptyLocked();
107 full_.Push(block);
108 if (was_empty) ml.Notify();
109 } else if (block->IsEmpty()) {
110 MutexLocker ml(global_mutex_);
111 global_empty_->Push(block);
112 TrimGlobalEmpty();
113 } else {
114 MonitorLocker ml(&monitor_);
115 bool was_empty = IsEmptyLocked();
116 partial_.Push(block);
117 if (was_empty) ml.Notify();
118 }
119}
120
121template <int BlockSize>
124 bool abort) {
125 MonitorLocker ml(&monitor_);
126 if (num_busy->fetch_sub(1u) == 1 /* 1 is before subtraction */) {
127 // This is the last worker, wake the others now that we know no further work
128 // will come.
129 ml.NotifyAll();
130 return nullptr;
131 }
132 if (abort) {
133 return nullptr;
134 }
135 for (;;) {
136 if (!full_.IsEmpty()) {
137 num_busy->fetch_add(1u);
138 return full_.Pop();
140 if (!partial_.IsEmpty()) {
141 num_busy->fetch_add(1u);
142 return partial_.Pop();
143 }
144 ml.Wait();
145 if (num_busy->load() == 0) {
146 return nullptr;
147 }
148 }
149}
150
151template <int Size>
153 // Generated code appends to store buffers; tell MemorySanitizer.
154 MSAN_UNPOISON(this, sizeof(*this));
155 visitor->VisitPointers(&pointers_[0], top_);
156}
157
160 if ((policy == kCheckThreshold) && Overflowed()) {
162 Thread* thread = Thread::Current();
163 // Sanity check: it makes no sense to schedule the GC in another isolate
164 // group.
165 // (If Isolate ever gets multiple store buffers, we should avoid this
166 // coupling by passing in an explicit callback+parameter at construction.)
167 ASSERT(thread->isolate_group()->store_buffer() == this);
169 }
170}
171
172template <int BlockSize>
175 {
176 MonitorLocker ml(&monitor_);
177 if (!partial_.IsEmpty()) {
178 return partial_.Pop();
179 }
180 }
181 return PopEmptyBlock();
182}
183
184template <int BlockSize>
186 {
187 MutexLocker ml(global_mutex_);
188 if (!global_empty_->IsEmpty()) {
189 return global_empty_->Pop();
190 }
191 }
192 return new Block();
193}
194
195template <int BlockSize>
198 MonitorLocker ml(&monitor_);
199 if (!full_.IsEmpty()) {
200 return full_.Pop();
201 } else if (!partial_.IsEmpty()) {
202 return partial_.Pop();
203 } else {
204 return nullptr;
205 }
206}
207
208template <int BlockSize>
210 MonitorLocker ml(&monitor_);
211 return IsEmptyLocked();
212}
213
214template <int BlockSize>
216 return full_.IsEmpty() && partial_.IsEmpty();
217}
218
219template <int BlockSize>
221 while (!IsEmpty()) {
222 delete Pop();
223 }
224}
225
226template <int BlockSize>
228 Block* result = head_;
229 head_ = head_->next_;
230 --length_;
231 result->next_ = nullptr;
232 return result;
233}
234
235template <int BlockSize>
237 Block* result = head_;
238 head_ = nullptr;
239 length_ = 0;
240 return result;
241}
242
243template <int BlockSize>
245 ASSERT(block->next_ == nullptr);
246 block->next_ = head_;
247 head_ = block;
248 ++length_;
249}
250
253 return (full_.length() + partial_.length()) > kMaxNonEmpty;
254}
255
257 ASSERT(Thread::Current()->OwnsGCSafepoint()); // No lock needed.
258 return full_.length() + partial_.length();
259}
260
261template <int BlockSize>
263 for (Block* block = full_.Peek(); block != nullptr; block = block->next()) {
264 block->VisitObjectPointers(visitor);
265 }
266 for (Block* block = partial_.Peek(); block != nullptr;
267 block = block->next()) {
268 block->VisitObjectPointers(visitor);
269 }
270}
271
272template <int BlockSize>
276 delete global_empty_->Pop();
277 }
278}
279
282
285
286} // 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
void Push(Block *block)
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:509
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
Definition: lockers.h:172
bool IsOwnedByCurrentThread() const
Definition: os_thread.h:402
virtual void VisitPointers(ObjectPtr *first, ObjectPtr *last)=0
PointerBlock< Size > * next() const
Definition: pointer_block.h:30
bool IsFull() const
Definition: pointer_block.h:34
void set_next(PointerBlock< Size > *next)
Definition: pointer_block.h:31
void VisitObjectPointers(ObjectPointerVisitor *visitor)
bool IsEmpty() const
Definition: pointer_block.h:35
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:710
@ kVMInterrupt
Definition: thread.h:488
static Thread * Current()
Definition: thread.h:362
void StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy)
Definition: thread.cc:791
void OldMarkingStackBlockProcess()
Definition: thread.cc:832
IsolateGroup * isolate_group() const
Definition: thread.h:541
void NewMarkingStackBlockProcess()
Definition: thread.cc:837
#define ASSERT(E)
GAsyncResult * result
#define MSAN_UNPOISON(ptr, len)
Definition: dart_vm.cc:33
DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread *thread)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network policy
Definition: switches.h:248
void Reset(SkPath *path)
Definition: path_ops.cc:40
#define END_LEAF_RUNTIME_ENTRY