Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Friends | List of all members
dart::GCCompactor Class Reference

#include <compactor.h>

Inheritance diagram for dart::GCCompactor:
dart::ValueObject dart::HandleVisitor dart::ObjectPointerVisitor

Public Member Functions

 GCCompactor (Thread *thread, Heap *heap)
 
 ~GCCompactor ()
 
void Compact (Page *pages, FreeList *freelist, Mutex *mutex)
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 
- Public Member Functions inherited from dart::HandleVisitor
 HandleVisitor (Thread *thread)
 
virtual ~HandleVisitor ()
 
Threadthread () const
 
virtual void VisitHandle (uword addr)=0
 
- Public Member Functions inherited from dart::ObjectPointerVisitor
 ObjectPointerVisitor (IsolateGroup *isolate_group)
 
virtual ~ObjectPointerVisitor ()
 
IsolateGroupisolate_group () const
 
virtual void VisitTypedDataViewPointers (TypedDataViewPtr view, CompressedObjectPtr *first, CompressedObjectPtr *last)
 
virtual void VisitPointers (ObjectPtr *first, ObjectPtr *last)=0
 
void VisitCompressedPointers (uword heap_base, CompressedObjectPtr *first, CompressedObjectPtr *last)
 
void VisitPointers (ObjectPtr *p, intptr_t len)
 
void VisitPointer (ObjectPtr *p)
 
const char * gc_root_type () const
 
void set_gc_root_type (const char *gc_root_type)
 
void clear_gc_root_type ()
 
virtual bool visit_weak_persistent_handles () const
 
virtual bool trace_values_through_fields () const
 
const ClassTableclass_table () const
 
virtual bool CanVisitSuspendStatePointers (SuspendStatePtr suspend_state)
 

Friends

class CompactorTask
 

Detailed Description

Definition at line 23 of file compactor.h.

Constructor & Destructor Documentation

◆ GCCompactor()

dart::GCCompactor::GCCompactor ( Thread thread,
Heap heap 
)
inline

Definition at line 27 of file compactor.h.

30 heap_(heap) {}
HandleVisitor(Thread *thread)
Thread * thread() const
ObjectPointerVisitor(IsolateGroup *isolate_group)
Definition: visitor.cc:11
IsolateGroup * isolate_group() const
Definition: thread.h:541

◆ ~GCCompactor()

dart::GCCompactor::~GCCompactor ( )
inline

Definition at line 31 of file compactor.h.

31{ free(image_page_ranges_); }

Member Function Documentation

◆ Compact()

void dart::GCCompactor::Compact ( Page pages,
FreeList freelist,
Mutex mutex 
)

Definition at line 184 of file compactor.cc.

184 {
185 SetupImagePageBoundaries();
186
187 Page* fixed_head = nullptr;
188 Page* fixed_tail = nullptr;
189
190 // Divide the heap, and set aside never-evacuate pages.
191 // TODO(30978): Try to divide based on live bytes or with work stealing.
192 intptr_t num_pages = 0;
193 Page* page = pages;
194 Page* prev = nullptr;
195 while (page != nullptr) {
196 Page* next = page->next();
197 if (page->is_never_evacuate()) {
198 if (prev != nullptr) {
199 prev->set_next(next);
200 } else {
201 pages = next;
202 }
203 if (fixed_tail == nullptr) {
204 fixed_tail = page;
205 }
206 page->set_next(fixed_head);
207 fixed_head = page;
208 } else {
209 prev = page;
210 num_pages++;
211 }
212 page = next;
213 }
214 fixed_pages_ = fixed_head;
215
216 intptr_t num_tasks = FLAG_compactor_tasks;
217 RELEASE_ASSERT(num_tasks >= 1);
218 if (num_pages < num_tasks) {
219 num_tasks = num_pages;
220 }
221 if (num_tasks == 0) {
222 ASSERT(pages == nullptr);
223
224 // Move pages to sweeper work lists.
225 heap_->old_space()->pages_ = nullptr;
226 heap_->old_space()->pages_tail_ = nullptr;
227 heap_->old_space()->sweep_regular_ = fixed_head;
228
229 heap_->old_space()->Sweep(/*exclusive*/ true);
230 heap_->old_space()->SweepLarge();
231 return;
232 }
233
234 Partition* partitions = new Partition[num_tasks];
235
236 {
237 const intptr_t pages_per_task = num_pages / num_tasks;
238 intptr_t task_index = 0;
239 intptr_t page_index = 0;
240 Page* page = pages;
241 Page* prev = nullptr;
242 while (task_index < num_tasks) {
243 ASSERT(!page->is_never_evacuate());
244 if (page_index % pages_per_task == 0) {
245 partitions[task_index].head = page;
246 partitions[task_index].tail = nullptr;
247 if (prev != nullptr) {
248 prev->set_next(nullptr);
249 }
250 task_index++;
251 }
252 prev = page;
253 page = page->next();
254 page_index++;
255 }
256 ASSERT(page_index <= num_pages);
257 ASSERT(task_index == num_tasks);
258 }
259
260 if (FLAG_force_evacuation) {
261 // Inject empty pages at the beginning of each worker's list to ensure all
262 // objects move and all pages that used to have an object are released.
263 // This can be helpful for finding untracked pointers because it prevents
264 // an untracked pointer from getting lucky with its target not moving.
265 bool oom = false;
266 for (intptr_t task_index = 0; task_index < num_tasks && !oom;
267 task_index++) {
268 const intptr_t pages_per_task = num_pages / num_tasks;
269 for (intptr_t j = 0; j < pages_per_task; j++) {
270 Page* page = heap_->old_space()->AllocatePage(/* exec */ false,
271 /* link */ false);
272
273 if (page == nullptr) {
274 oom = true;
275 break;
276 }
277
278 FreeListElement::AsElement(page->object_start(),
279 page->object_end() - page->object_start());
280
281 // The compactor slides down: add the empty pages to the beginning.
282 page->set_next(partitions[task_index].head);
283 partitions[task_index].head = page;
284 }
285 }
286 }
287
288 {
289 ThreadBarrier* barrier = new ThreadBarrier(num_tasks, 1);
290 RelaxedAtomic<intptr_t> next_planning_task = {0};
291 RelaxedAtomic<intptr_t> next_setup_task = {0};
292 RelaxedAtomic<intptr_t> next_sliding_task = {0};
293 RelaxedAtomic<intptr_t> next_forwarding_task = {0};
294
295 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
296 if (task_index < (num_tasks - 1)) {
297 // Begin compacting on a helper thread.
299 thread()->isolate_group(), this, barrier, &next_planning_task,
300 &next_setup_task, &next_sliding_task, &next_forwarding_task,
301 num_tasks, partitions, freelist);
302 } else {
303 // Last worker is the main thread.
304 CompactorTask task(thread()->isolate_group(), this, barrier,
305 &next_planning_task, &next_setup_task,
306 &next_sliding_task, &next_forwarding_task, num_tasks,
307 partitions, freelist);
308 task.RunEnteredIsolateGroup();
309 barrier->Sync();
310 barrier->Release();
311 }
312 }
313 }
314
315 // Update inner pointers in typed data views (needs to be done after all
316 // threads are done with sliding since we need to access fields of the
317 // view's backing store)
318 //
319 // (If the sliding compactor was single-threaded we could do this during the
320 // sliding phase: The class id of the backing store can be either accessed by
321 // looking at the already-slided-object or the not-yet-slided object. Though
322 // with parallel sliding there is no safe way to access the backing store
323 // object header.)
324 {
326 "ForwardTypedDataViewInternalPointers");
327 const intptr_t length = typed_data_views_.length();
328 for (intptr_t i = 0; i < length; ++i) {
329 auto raw_view = typed_data_views_[i];
330 const classid_t cid =
331 raw_view->untag()->typed_data()->GetClassIdMayBeSmi();
332
333 // If we have external typed data we can simply return, since the backing
334 // store lives in C-heap and will not move. Otherwise we have to update
335 // the inner pointer.
336 if (IsTypedDataClassId(cid)) {
337 raw_view->untag()->RecomputeDataFieldForInternalTypedData();
338 } else {
340 }
341 }
342 }
343
344 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
345 ASSERT(partitions[task_index].tail != nullptr);
346 }
347
348 {
349 TIMELINE_FUNCTION_GC_DURATION(thread(), "ForwardStackPointers");
350 ForwardStackPointers();
351 }
352
353 {
355 "ForwardPostponedSuspendStatePointers");
356 // After heap sliding is complete and ObjectStore pointers are forwarded
357 // it is finally safe to visit SuspendState objects with copied frames.
358 can_visit_stack_frames_ = true;
359 const intptr_t length = postponed_suspend_states_.length();
360 for (intptr_t i = 0; i < length; ++i) {
361 auto suspend_state = postponed_suspend_states_[i];
362 suspend_state->untag()->VisitPointers(this);
363 }
364 }
365
366 heap_->old_space()->VisitRoots(this);
367
368 {
369 MutexLocker ml(pages_lock);
370
371 // Free empty pages.
372 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
373 Page* page = partitions[task_index].tail->next();
374 while (page != nullptr) {
375 Page* next = page->next();
377 -(page->memory_->size() >> kWordSizeLog2));
378 page->Deallocate();
379 page = next;
380 }
381 }
382
383 // Re-join the heap.
384 for (intptr_t task_index = 0; task_index < num_tasks - 1; task_index++) {
385 partitions[task_index].tail->set_next(partitions[task_index + 1].head);
386 }
387 partitions[num_tasks - 1].tail->set_next(nullptr);
388 heap_->old_space()->pages_ = pages = partitions[0].head;
389 heap_->old_space()->pages_tail_ = partitions[num_tasks - 1].tail;
390 if (fixed_head != nullptr) {
391 fixed_tail->set_next(heap_->old_space()->pages_);
392 heap_->old_space()->pages_ = fixed_head;
393
394 ASSERT(heap_->old_space()->pages_tail_ != nullptr);
395 }
396
397 delete[] partitions;
398 }
399}
static float next(float f)
static float prev(float f)
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
intptr_t length() const
static ThreadPool * thread_pool()
Definition: dart.h:73
static FreeListElement * AsElement(uword addr, intptr_t size)
Definition: freelist.cc:16
friend class CompactorTask
Definition: compactor.h:36
PageSpace * old_space()
Definition: heap.h:63
IsolateGroup * isolate_group() const
Definition: visitor.h:25
void IncreaseCapacityInWordsLocked(intptr_t increase_in_words)
Definition: pages.h:203
void VisitRoots(ObjectPointerVisitor *visitor)
Definition: pages.cc:962
void set_next(Page *next)
Definition: page.h:103
bool Run(Args &&... args)
Definition: thread_pool.h:45
#define ASSERT(E)
size_t length
bool IsTypedDataClassId(intptr_t index)
Definition: class_id.h:433
int32_t classid_t
Definition: globals.h:524
constexpr intptr_t kWordSizeLog2
Definition: globals.h:507
const intptr_t cid
bool IsExternalTypedDataClassId(intptr_t index)
Definition: class_id.h:447
#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
Definition: timeline.h:41

Friends And Related Function Documentation

◆ CompactorTask

friend class CompactorTask
friend

Definition at line 36 of file compactor.h.


The documentation for this class was generated from the following files: