Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private 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
 
- Public Member Functions inherited from dart::ObjectPointerVisitor
 ObjectPointerVisitor (IsolateGroup *isolate_group)
 
virtual ~ObjectPointerVisitor ()
 
IsolateGroupisolate_group () const
 
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
 

Private Member Functions

void VisitTypedDataViewPointers (TypedDataViewPtr view, CompressedObjectPtr *first, CompressedObjectPtr *last) override
 
void VisitPointers (ObjectPtr *first, ObjectPtr *last) override
 
bool CanVisitSuspendStatePointers (SuspendStatePtr suspend_state) override
 
void VisitHandle (uword addr) override
 

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:540

◆ ~GCCompactor()

dart::GCCompactor::~GCCompactor ( )
inline

Definition at line 31 of file compactor.h.

31{ free(image_page_ranges_); }

Member Function Documentation

◆ CanVisitSuspendStatePointers()

bool dart::GCCompactor::CanVisitSuspendStatePointers ( SuspendStatePtr  suspend_state)
overrideprivatevirtual

Reimplemented from dart::ObjectPointerVisitor.

Definition at line 765 of file compactor.cc.

765 {
766 if ((suspend_state->untag()->pc() != 0) && !can_visit_stack_frames_) {
767 // Visiting pointers of SuspendState objects with copied stack frame
768 // needs to query stack map, which can touch other Dart objects
769 // (such as GrowableObjectArray of InstructionsTable).
770 // Those objects may have an inconsistent state during compaction,
771 // so processing of SuspendState objects is postponed to the later
772 // stage of compaction.
773 MutexLocker ml(&postponed_suspend_states_mutex_);
774 postponed_suspend_states_.Add(suspend_state);
775 return false;
776 }
777 return true;
778}
void Add(const T &value)

◆ Compact()

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

Definition at line 184 of file compactor.cc.

184 {
185 SetupImagePageBoundaries();
186
187 // Divide the heap.
188 // TODO(30978): Try to divide based on live bytes or with work stealing.
189 intptr_t num_pages = 0;
190 for (Page* page = pages; page != nullptr; page = page->next()) {
191 num_pages++;
192 }
193
194 intptr_t num_tasks = FLAG_compactor_tasks;
195 RELEASE_ASSERT(num_tasks >= 1);
196 if (num_pages < num_tasks) {
197 num_tasks = num_pages;
198 }
199
200 Partition* partitions = new Partition[num_tasks];
201
202 {
203 const intptr_t pages_per_task = num_pages / num_tasks;
204 intptr_t task_index = 0;
205 intptr_t page_index = 0;
206 Page* page = pages;
207 Page* prev = nullptr;
208 while (task_index < num_tasks) {
209 if (page_index % pages_per_task == 0) {
210 partitions[task_index].head = page;
211 partitions[task_index].tail = nullptr;
212 if (prev != nullptr) {
213 prev->set_next(nullptr);
214 }
215 task_index++;
216 }
217 prev = page;
218 page = page->next();
219 page_index++;
220 }
221 ASSERT(page_index <= num_pages);
222 ASSERT(task_index == num_tasks);
223 }
224
225 if (FLAG_force_evacuation) {
226 // Inject empty pages at the beginning of each worker's list to ensure all
227 // objects move and all pages that used to have an object are released.
228 // This can be helpful for finding untracked pointers because it prevents
229 // an untracked pointer from getting lucky with its target not moving.
230 bool oom = false;
231 for (intptr_t task_index = 0; task_index < num_tasks && !oom;
232 task_index++) {
233 const intptr_t pages_per_task = num_pages / num_tasks;
234 for (intptr_t j = 0; j < pages_per_task; j++) {
235 Page* page = heap_->old_space()->AllocatePage(/* exec */ false,
236 /* link */ false);
237
238 if (page == nullptr) {
239 oom = true;
240 break;
241 }
242
243 FreeListElement::AsElement(page->object_start(),
244 page->object_end() - page->object_start());
245
246 // The compactor slides down: add the empty pages to the beginning.
247 page->set_next(partitions[task_index].head);
248 partitions[task_index].head = page;
249 }
250 }
251 }
252
253 {
254 ThreadBarrier* barrier = new ThreadBarrier(num_tasks, 1);
255 RelaxedAtomic<intptr_t> next_planning_task = {0};
256 RelaxedAtomic<intptr_t> next_setup_task = {0};
257 RelaxedAtomic<intptr_t> next_sliding_task = {0};
258 RelaxedAtomic<intptr_t> next_forwarding_task = {0};
259
260 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
261 if (task_index < (num_tasks - 1)) {
262 // Begin compacting on a helper thread.
264 thread()->isolate_group(), this, barrier, &next_planning_task,
265 &next_setup_task, &next_sliding_task, &next_forwarding_task,
266 num_tasks, partitions, freelist);
267 } else {
268 // Last worker is the main thread.
269 CompactorTask task(thread()->isolate_group(), this, barrier,
270 &next_planning_task, &next_setup_task,
271 &next_sliding_task, &next_forwarding_task, num_tasks,
272 partitions, freelist);
273 task.RunEnteredIsolateGroup();
274 barrier->Sync();
275 barrier->Release();
276 }
277 }
278 }
279
280 // Update inner pointers in typed data views (needs to be done after all
281 // threads are done with sliding since we need to access fields of the
282 // view's backing store)
283 //
284 // (If the sliding compactor was single-threaded we could do this during the
285 // sliding phase: The class id of the backing store can be either accessed by
286 // looking at the already-slided-object or the not-yet-slided object. Though
287 // with parallel sliding there is no safe way to access the backing store
288 // object header.)
289 {
291 "ForwardTypedDataViewInternalPointers");
292 const intptr_t length = typed_data_views_.length();
293 for (intptr_t i = 0; i < length; ++i) {
294 auto raw_view = typed_data_views_[i];
295 const classid_t cid =
296 raw_view->untag()->typed_data()->GetClassIdMayBeSmi();
297
298 // If we have external typed data we can simply return, since the backing
299 // store lives in C-heap and will not move. Otherwise we have to update
300 // the inner pointer.
301 if (IsTypedDataClassId(cid)) {
302 raw_view->untag()->RecomputeDataFieldForInternalTypedData();
303 } else {
305 }
306 }
307 }
308
309 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
310 ASSERT(partitions[task_index].tail != nullptr);
311 }
312
313 {
314 TIMELINE_FUNCTION_GC_DURATION(thread(), "ForwardStackPointers");
315 ForwardStackPointers();
316 }
317
318 {
320 "ForwardPostponedSuspendStatePointers");
321 // After heap sliding is complete and ObjectStore pointers are forwarded
322 // it is finally safe to visit SuspendState objects with copied frames.
323 can_visit_stack_frames_ = true;
324 const intptr_t length = postponed_suspend_states_.length();
325 for (intptr_t i = 0; i < length; ++i) {
326 auto suspend_state = postponed_suspend_states_[i];
327 suspend_state->untag()->VisitPointers(this);
328 }
329 }
330
331 heap_->old_space()->VisitRoots(this);
332
333 {
334 MutexLocker ml(pages_lock);
335
336 // Free empty pages.
337 for (intptr_t task_index = 0; task_index < num_tasks; task_index++) {
338 Page* page = partitions[task_index].tail->next();
339 while (page != nullptr) {
340 Page* next = page->next();
342 -(page->memory_->size() >> kWordSizeLog2));
343 page->Deallocate();
344 page = next;
345 }
346 }
347
348 // Re-join the heap.
349 for (intptr_t task_index = 0; task_index < num_tasks - 1; task_index++) {
350 partitions[task_index].tail->set_next(partitions[task_index + 1].head);
351 }
352 partitions[num_tasks - 1].tail->set_next(nullptr);
353 heap_->old_space()->pages_ = pages = partitions[0].head;
354 heap_->old_space()->pages_tail_ = partitions[num_tasks - 1].tail;
355
356 delete[] partitions;
357 }
358}
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:198
void VisitRoots(ObjectPointerVisitor *visitor)
Definition pages.cc:949
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

◆ VisitHandle()

void dart::GCCompactor::VisitHandle ( uword  addr)
overrideprivatevirtual

Implements dart::HandleVisitor.

Definition at line 780 of file compactor.cc.

780 {
781 FinalizablePersistentHandle* handle =
782 reinterpret_cast<FinalizablePersistentHandle*>(addr);
783 ForwardPointer(handle->ptr_addr());
784}

◆ VisitPointers()

void dart::GCCompactor::VisitPointers ( ObjectPtr first,
ObjectPtr last 
)
overrideprivatevirtual

Implements dart::ObjectPointerVisitor.

Definition at line 749 of file compactor.cc.

749 {
750 for (ObjectPtr* ptr = first; ptr <= last; ptr++) {
751 ForwardPointer(ptr);
752 }
753}

◆ VisitTypedDataViewPointers()

void dart::GCCompactor::VisitTypedDataViewPointers ( TypedDataViewPtr  view,
CompressedObjectPtr first,
CompressedObjectPtr last 
)
overrideprivatevirtual

Reimplemented from dart::ObjectPointerVisitor.

Definition at line 713 of file compactor.cc.

715 {
716 // First we forward all fields of the typed data view.
717 ObjectPtr old_backing = view->untag()->typed_data();
718 VisitCompressedPointers(view->heap_base(), first, last);
719 ObjectPtr new_backing = view->untag()->typed_data();
720
721 const bool backing_moved = old_backing != new_backing;
722 if (backing_moved) {
723 // The backing store moved, so we *might* need to update the view's inner
724 // pointer. If the backing store is internal typed data we *have* to update
725 // it, otherwise (in case of external typed data) we don't have to.
726 //
727 // Unfortunately we cannot find out whether the backing store is internal
728 // or external during sliding phase: Even though we know the old and new
729 // location of the backing store another thread might be responsible for
730 // moving it and we have no way to tell when it got moved.
731 //
732 // So instead we queue all those views up and fix their inner pointer in a
733 // final phase after compaction.
734 MutexLocker ml(&typed_data_view_mutex_);
735 typed_data_views_.Add(view);
736 } else {
737 // The backing store didn't move, we therefore don't need to update the
738 // inner pointer.
739 if (view->untag()->data_ == nullptr) {
740 ASSERT(RawSmiValue(view->untag()->offset_in_bytes()) == 0 &&
741 RawSmiValue(view->untag()->length()) == 0 &&
742 view->untag()->typed_data() == Object::null());
743 }
744 }
745}
void VisitCompressedPointers(uword heap_base, CompressedObjectPtr *first, CompressedObjectPtr *last)
Definition visitor.h:43
static ObjectPtr null()
Definition object.h:433
intptr_t RawSmiValue(const SmiPtr raw_value)

Friends And Related Symbol 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: