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

Side by Side Diff: src/heap/mark-compact.cc

Issue 1871423002: [heap] Refactor Sweeper (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Comments round 2 Created 4 years, 8 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
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/mark-compact-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/heap/mark-compact.h" 5 #include "src/heap/mark-compact.h"
6 6
7 #include "src/base/atomicops.h" 7 #include "src/base/atomicops.h"
8 #include "src/base/bits.h" 8 #include "src/base/bits.h"
9 #include "src/base/sys-info.h" 9 #include "src/base/sys-info.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 #endif 54 #endif
55 marking_parity_(ODD_MARKING_PARITY), 55 marking_parity_(ODD_MARKING_PARITY),
56 was_marked_incrementally_(false), 56 was_marked_incrementally_(false),
57 evacuation_(false), 57 evacuation_(false),
58 heap_(heap), 58 heap_(heap),
59 marking_deque_memory_(NULL), 59 marking_deque_memory_(NULL),
60 marking_deque_memory_committed_(0), 60 marking_deque_memory_committed_(0),
61 code_flusher_(nullptr), 61 code_flusher_(nullptr),
62 have_code_to_deoptimize_(false), 62 have_code_to_deoptimize_(false),
63 compacting_(false), 63 compacting_(false),
64 sweeping_in_progress_(false), 64 pending_compaction_tasks_semaphore_(0),
65 pending_sweeper_tasks_semaphore_(0), 65 sweeper_(heap) {
66 pending_compaction_tasks_semaphore_(0) {
67 } 66 }
68 67
69 #ifdef VERIFY_HEAP 68 #ifdef VERIFY_HEAP
70 class VerifyMarkingVisitor : public ObjectVisitor { 69 class VerifyMarkingVisitor : public ObjectVisitor {
71 public: 70 public:
72 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} 71 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {}
73 72
74 void VisitPointers(Object** start, Object** end) override { 73 void VisitPointers(Object** start, Object** end) override {
75 for (Object** current = start; current < end; current++) { 74 for (Object** current = start; current < end; current++) {
76 if ((*current)->IsHeapObject()) { 75 if ((*current)->IsHeapObject()) {
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 Marking::MarkWhite(Marking::MarkBitFrom(obj)); 451 Marking::MarkWhite(Marking::MarkBitFrom(obj));
453 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); 452 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
454 chunk->ResetProgressBar(); 453 chunk->ResetProgressBar();
455 chunk->ResetLiveBytes(); 454 chunk->ResetLiveBytes();
456 if (chunk->IsFlagSet(Page::BLACK_PAGE)) { 455 if (chunk->IsFlagSet(Page::BLACK_PAGE)) {
457 chunk->ClearFlag(Page::BLACK_PAGE); 456 chunk->ClearFlag(Page::BLACK_PAGE);
458 } 457 }
459 } 458 }
460 } 459 }
461 460
462 461 class MarkCompactCollector::Sweeper::SweeperTask : public v8::Task {
463 class MarkCompactCollector::SweeperTask : public v8::Task {
464 public: 462 public:
465 SweeperTask(Heap* heap, AllocationSpace space_to_start) 463 SweeperTask(Sweeper* sweeper, base::Semaphore* pending_sweeper_tasks,
466 : heap_(heap), space_to_start_(space_to_start) {} 464 AllocationSpace space_to_start)
465 : sweeper_(sweeper),
466 pending_sweeper_tasks_(pending_sweeper_tasks),
467 space_to_start_(space_to_start) {}
467 468
468 virtual ~SweeperTask() {} 469 virtual ~SweeperTask() {}
469 470
470 private: 471 private:
471 // v8::Task overrides. 472 // v8::Task overrides.
472 void Run() override { 473 void Run() override {
473 DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE); 474 DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE);
474 DCHECK_LE(space_to_start_, LAST_PAGED_SPACE); 475 DCHECK_LE(space_to_start_, LAST_PAGED_SPACE);
475 const int offset = space_to_start_ - FIRST_PAGED_SPACE; 476 const int offset = space_to_start_ - FIRST_PAGED_SPACE;
476 const int num_spaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; 477 const int num_spaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
477 for (int i = 0; i < num_spaces; i++) { 478 for (int i = 0; i < num_spaces; i++) {
478 const int space_id = FIRST_PAGED_SPACE + ((i + offset) % num_spaces); 479 const int space_id = FIRST_PAGED_SPACE + ((i + offset) % num_spaces);
479 DCHECK_GE(space_id, FIRST_PAGED_SPACE); 480 DCHECK_GE(space_id, FIRST_PAGED_SPACE);
480 DCHECK_LE(space_id, LAST_PAGED_SPACE); 481 DCHECK_LE(space_id, LAST_PAGED_SPACE);
481 heap_->mark_compact_collector()->SweepInParallel( 482 sweeper_->ParallelSweepSpace(static_cast<AllocationSpace>(space_id), 0);
482 heap_->paged_space(space_id), 0);
483 } 483 }
484 heap_->mark_compact_collector()->pending_sweeper_tasks_semaphore_.Signal(); 484 pending_sweeper_tasks_->Signal();
485 } 485 }
486 486
487 Heap* heap_; 487 Sweeper* sweeper_;
488 base::Semaphore* pending_sweeper_tasks_;
488 AllocationSpace space_to_start_; 489 AllocationSpace space_to_start_;
489 490
490 DISALLOW_COPY_AND_ASSIGN(SweeperTask); 491 DISALLOW_COPY_AND_ASSIGN(SweeperTask);
491 }; 492 };
492 493
493 494 void MarkCompactCollector::Sweeper::StartSweeping() {
494 void MarkCompactCollector::StartSweeperThreads() { 495 sweeping_in_progress_ = true;
495 V8::GetCurrentPlatform()->CallOnBackgroundThread( 496 ForAllSweepingSpaces([this](AllocationSpace space) {
496 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); 497 std::sort(sweeping_list_[space].begin(), sweeping_list_[space].end(),
497 V8::GetCurrentPlatform()->CallOnBackgroundThread( 498 [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); });
498 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); 499 });
499 V8::GetCurrentPlatform()->CallOnBackgroundThread( 500 if (FLAG_concurrent_sweeping) {
500 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask); 501 ForAllSweepingSpaces([this](AllocationSpace space) {
502 if (space == NEW_SPACE) return;
503 StartSweepingHelper(space);
504 });
505 }
501 } 506 }
502 507
508 void MarkCompactCollector::Sweeper::StartSweepingHelper(
509 AllocationSpace space_to_start) {
510 num_sweeping_tasks_++;
511 V8::GetCurrentPlatform()->CallOnBackgroundThread(
512 new SweeperTask(this, &pending_sweeper_tasks_semaphore_, space_to_start),
513 v8::Platform::kShortRunningTask);
514 }
503 515
504 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { 516 void MarkCompactCollector::Sweeper::SweepOrWaitUntilSweepingCompleted(
517 Page* page) {
505 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner()); 518 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
506 if (!page->SweepingDone()) { 519 if (!page->SweepingDone()) {
507 SweepInParallel(page, owner); 520 ParallelSweepPage(page, owner);
508 if (!page->SweepingDone()) { 521 if (!page->SweepingDone()) {
509 // We were not able to sweep that page, i.e., a concurrent 522 // We were not able to sweep that page, i.e., a concurrent
510 // sweeper thread currently owns this page. Wait for the sweeper 523 // sweeper thread currently owns this page. Wait for the sweeper
511 // thread to be done with this page. 524 // thread to be done with this page.
512 page->WaitUntilSweepingCompleted(); 525 page->WaitUntilSweepingCompleted();
513 } 526 }
514 } 527 }
515 } 528 }
516 529
517
518 void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) { 530 void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) {
519 if (FLAG_concurrent_sweeping && !IsSweepingCompleted()) { 531 if (FLAG_concurrent_sweeping && !sweeper().IsSweepingCompleted()) {
520 SweepInParallel(heap()->paged_space(space->identity()), 0); 532 sweeper().ParallelSweepSpace(space->identity(), 0);
521 space->RefillFreeList(); 533 space->RefillFreeList();
522 } 534 }
523 } 535 }
524 536
537 Page* MarkCompactCollector::Sweeper::GetSweptPageSafe(PagedSpace* space) {
538 base::LockGuard<base::Mutex> guard(&mutex_);
539 SweptList& list = swept_list_[space->identity()];
540 if (list.length() > 0) {
541 return list.RemoveLast();
542 }
543 return nullptr;
544 }
525 545
526 void MarkCompactCollector::EnsureSweepingCompleted() { 546 void MarkCompactCollector::Sweeper::EnsureCompleted() {
527 DCHECK(sweeping_in_progress_ == true); 547 DCHECK(sweeping_in_progress_ == true);
528 548
529 // If sweeping is not completed or not running at all, we try to complete it 549 // If sweeping is not completed or not running at all, we try to complete it
530 // here. 550 // here.
531 if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) { 551 if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) {
532 SweepInParallel(heap()->paged_space(OLD_SPACE), 0); 552 ForAllSweepingSpaces(
533 SweepInParallel(heap()->paged_space(CODE_SPACE), 0); 553 [this](AllocationSpace space) { ParallelSweepSpace(space, 0); });
534 SweepInParallel(heap()->paged_space(MAP_SPACE), 0);
535 } 554 }
536 555
537 if (FLAG_concurrent_sweeping) { 556 if (FLAG_concurrent_sweeping) {
538 pending_sweeper_tasks_semaphore_.Wait(); 557 while (num_sweeping_tasks_ > 0) {
539 pending_sweeper_tasks_semaphore_.Wait(); 558 pending_sweeper_tasks_semaphore_.Wait();
540 pending_sweeper_tasks_semaphore_.Wait(); 559 num_sweeping_tasks_--;
560 }
541 } 561 }
542 562
543 ParallelSweepSpacesComplete(); 563 DCHECK(sweeping_list_[NEW_SPACE].empty());
564 ForAllSweepingSpaces([this](AllocationSpace space) {
565 DCHECK_NULL(tmp_late_sweeping_list_[space]);
566 sweeping_list_[space].clear();
567 if (late_sweeping_list_[space] != nullptr) {
568 delete late_sweeping_list_[space];
569 }
570 });
571
544 sweeping_in_progress_ = false; 572 sweeping_in_progress_ = false;
573 }
574
575 void MarkCompactCollector::EnsureSweepingCompleted() {
576 DCHECK(sweeper().sweeping_in_progress() == true);
577
578 sweeper().EnsureCompleted();
545 heap()->old_space()->RefillFreeList(); 579 heap()->old_space()->RefillFreeList();
546 heap()->code_space()->RefillFreeList(); 580 heap()->code_space()->RefillFreeList();
547 heap()->map_space()->RefillFreeList(); 581 heap()->map_space()->RefillFreeList();
548 582
549 #ifdef VERIFY_HEAP 583 #ifdef VERIFY_HEAP
550 if (FLAG_verify_heap && !evacuation()) { 584 if (FLAG_verify_heap && !evacuation()) {
551 VerifyEvacuation(heap_); 585 VerifyEvacuation(heap_);
552 } 586 }
553 #endif 587 #endif
554 } 588 }
555 589
556 590 bool MarkCompactCollector::Sweeper::IsSweepingCompleted() {
557 bool MarkCompactCollector::IsSweepingCompleted() {
558 if (!pending_sweeper_tasks_semaphore_.WaitFor( 591 if (!pending_sweeper_tasks_semaphore_.WaitFor(
559 base::TimeDelta::FromSeconds(0))) { 592 base::TimeDelta::FromSeconds(0))) {
560 return false; 593 return false;
561 } 594 }
562 pending_sweeper_tasks_semaphore_.Signal(); 595 pending_sweeper_tasks_semaphore_.Signal();
563 return true; 596 return true;
564 } 597 }
565 598
566
567 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { 599 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) {
568 // This is only used when resizing an object. 600 // This is only used when resizing an object.
569 DCHECK(MemoryChunk::FromAddress(old_start) == 601 DCHECK(MemoryChunk::FromAddress(old_start) ==
570 MemoryChunk::FromAddress(new_start)); 602 MemoryChunk::FromAddress(new_start));
571 603
572 if (!heap->incremental_marking()->IsMarking() || 604 if (!heap->incremental_marking()->IsMarking() ||
573 Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE)) 605 Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE))
574 return; 606 return;
575 607
576 // If the mark doesn't move, we don't check the color of the object. 608 // If the mark doesn't move, we don't check the color of the object.
(...skipping 2585 matching lines...) Expand 10 before | Expand all | Expand 10 after
3162 HeapObject* heap_object = HeapObject::cast(object); 3194 HeapObject* heap_object = HeapObject::cast(object);
3163 MapWord map_word = heap_object->map_word(); 3195 MapWord map_word = heap_object->map_word();
3164 if (map_word.IsForwardingAddress()) { 3196 if (map_word.IsForwardingAddress()) {
3165 return map_word.ToForwardingAddress(); 3197 return map_word.ToForwardingAddress();
3166 } 3198 }
3167 } 3199 }
3168 return object; 3200 return object;
3169 } 3201 }
3170 }; 3202 };
3171 3203
3172 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; 3204 template <MarkCompactCollector::Sweeper::SweepingMode sweeping_mode,
3173 3205 MarkCompactCollector::Sweeper::SweepingParallelism parallelism,
3174 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; 3206 MarkCompactCollector::Sweeper::SkipListRebuildingMode skip_list_mode,
3175 3207 MarkCompactCollector::Sweeper::FreeSpaceTreatmentMode free_space_mode>
3176 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; 3208 int MarkCompactCollector::Sweeper::RawSweep(PagedSpace* space, Page* p,
3177 3209 ObjectVisitor* v) {
3178 // Sweeps a page. After sweeping the page can be iterated.
3179 // Slots in live objects pointing into evacuation candidates are updated
3180 // if requested.
3181 // Returns the size of the biggest continuous freed memory chunk in bytes.
3182 template <SweepingMode sweeping_mode,
3183 MarkCompactCollector::SweepingParallelism parallelism,
3184 SkipListRebuildingMode skip_list_mode,
3185 FreeSpaceTreatmentMode free_space_mode>
3186 static int Sweep(PagedSpace* space, Page* p, ObjectVisitor* v) {
3187 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); 3210 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone());
3188 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); 3211 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE));
3189 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, 3212 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST,
3190 space->identity() == CODE_SPACE); 3213 space->identity() == CODE_SPACE);
3191 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); 3214 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST));
3192 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || 3215 DCHECK(parallelism == SWEEP_ON_MAIN_THREAD || sweeping_mode == SWEEP_ONLY);
3193 sweeping_mode == SWEEP_ONLY);
3194 3216
3195 Address free_start = p->area_start(); 3217 Address free_start = p->area_start();
3196 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); 3218 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
3197 3219
3198 // If we use the skip list for code space pages, we have to lock the skip 3220 // If we use the skip list for code space pages, we have to lock the skip
3199 // list because it could be accessed concurrently by the runtime or the 3221 // list because it could be accessed concurrently by the runtime or the
3200 // deoptimizer. 3222 // deoptimizer.
3201 SkipList* skip_list = p->skip_list(); 3223 SkipList* skip_list = p->skip_list();
3202 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { 3224 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) {
3203 skip_list->Clear(); 3225 skip_list->Clear();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 if (free_space_mode == ZAP_FREE_SPACE) { 3267 if (free_space_mode == ZAP_FREE_SPACE) {
3246 memset(free_start, 0xcc, size); 3268 memset(free_start, 0xcc, size);
3247 } 3269 }
3248 freed_bytes = space->UnaccountedFree(free_start, size); 3270 freed_bytes = space->UnaccountedFree(free_start, size);
3249 max_freed_bytes = Max(freed_bytes, max_freed_bytes); 3271 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3250 } 3272 }
3251 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); 3273 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3252 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3274 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3253 } 3275 }
3254 3276
3255
3256 void MarkCompactCollector::InvalidateCode(Code* code) { 3277 void MarkCompactCollector::InvalidateCode(Code* code) {
3257 if (heap_->incremental_marking()->IsCompacting() && 3278 if (heap_->incremental_marking()->IsCompacting() &&
3258 !ShouldSkipEvacuationSlotRecording(code)) { 3279 !ShouldSkipEvacuationSlotRecording(code)) {
3259 DCHECK(compacting_); 3280 DCHECK(compacting_);
3260 3281
3261 // If the object is white than no slots were recorded on it yet. 3282 // If the object is white than no slots were recorded on it yet.
3262 MarkBit mark_bit = Marking::MarkBitFrom(code); 3283 MarkBit mark_bit = Marking::MarkBitFrom(code);
3263 if (Marking::IsWhite(mark_bit)) return; 3284 if (Marking::IsWhite(mark_bit)) return;
3264 3285
3265 // Ignore all slots that might have been recorded in the body of the 3286 // Ignore all slots that might have been recorded in the body of the
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3342 LiveObjectIterator<kBlackObjects> it(page); 3363 LiveObjectIterator<kBlackObjects> it(page);
3343 HeapObject* object = NULL; 3364 HeapObject* object = NULL;
3344 while ((object = it.Next()) != NULL) { 3365 while ((object = it.Next()) != NULL) {
3345 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 3366 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3346 Map* map = object->synchronized_map(); 3367 Map* map = object->synchronized_map();
3347 int size = object->SizeFromMap(map); 3368 int size = object->SizeFromMap(map);
3348 object->IterateBody(map->instance_type(), size, visitor); 3369 object->IterateBody(map->instance_type(), size, visitor);
3349 } 3370 }
3350 } 3371 }
3351 3372
3373 void MarkCompactCollector::Sweeper::AddSweptPageSafe(PagedSpace* space,
3374 Page* page) {
3375 base::LockGuard<base::Mutex> guard(&mutex_);
3376 swept_list_[space->identity()].Add(page);
3377 }
3352 3378
3353 void MarkCompactCollector::SweepAbortedPages() { 3379 void MarkCompactCollector::SweepAbortedPages() {
3354 // Second pass on aborted pages. 3380 // Second pass on aborted pages.
3355 for (Page* p : evacuation_candidates_) { 3381 for (Page* p : evacuation_candidates_) {
3356 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { 3382 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3357 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); 3383 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
3358 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); 3384 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
3359 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); 3385 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3360 switch (space->identity()) { 3386 switch (space->identity()) {
3361 case OLD_SPACE: 3387 case OLD_SPACE:
3362 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, 3388 Sweeper::RawSweep<Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3363 IGNORE_FREE_SPACE>(space, p, nullptr); 3389 Sweeper::IGNORE_SKIP_LIST,
3390 Sweeper::IGNORE_FREE_SPACE>(space, p, nullptr);
3364 break; 3391 break;
3365 case CODE_SPACE: 3392 case CODE_SPACE:
3366 if (FLAG_zap_code_space) { 3393 if (FLAG_zap_code_space) {
3367 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, 3394 Sweeper::RawSweep<
3368 ZAP_FREE_SPACE>(space, p, nullptr); 3395 Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3396 Sweeper::REBUILD_SKIP_LIST, Sweeper::ZAP_FREE_SPACE>(space, p,
3397 nullptr);
3369 } else { 3398 } else {
3370 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, 3399 Sweeper::RawSweep<
3371 IGNORE_FREE_SPACE>(space, p, nullptr); 3400 Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3401 Sweeper::REBUILD_SKIP_LIST, Sweeper::IGNORE_FREE_SPACE>(
3402 space, p, nullptr);
3372 } 3403 }
3373 break; 3404 break;
3374 default: 3405 default:
3375 UNREACHABLE(); 3406 UNREACHABLE();
3376 break; 3407 break;
3377 } 3408 }
3378 { 3409 sweeper().AddSweptPageSafe(space, p);
3379 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_);
3380 swept_pages(space->identity())->Add(p);
3381 }
3382 } 3410 }
3383 } 3411 }
3384 } 3412 }
3385 3413
3386 3414
3387 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { 3415 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
3388 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); 3416 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE);
3389 Heap::RelocationLock relocation_lock(heap()); 3417 Heap::RelocationLock relocation_lock(heap());
3390 3418
3391 { 3419 {
(...skipping 23 matching lines...) Expand all
3415 // EvacuateNewSpaceAndCandidates iterates over new space objects and for 3443 // EvacuateNewSpaceAndCandidates iterates over new space objects and for
3416 // ArrayBuffers either re-registers them as live or promotes them. This is 3444 // ArrayBuffers either re-registers them as live or promotes them. This is
3417 // needed to properly free them. 3445 // needed to properly free them.
3418 heap()->array_buffer_tracker()->FreeDead(false); 3446 heap()->array_buffer_tracker()->FreeDead(false);
3419 3447
3420 // Deallocate evacuated candidate pages. 3448 // Deallocate evacuated candidate pages.
3421 ReleaseEvacuationCandidates(); 3449 ReleaseEvacuationCandidates();
3422 } 3450 }
3423 3451
3424 #ifdef VERIFY_HEAP 3452 #ifdef VERIFY_HEAP
3425 if (FLAG_verify_heap && !sweeping_in_progress_) { 3453 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) {
3426 VerifyEvacuation(heap()); 3454 VerifyEvacuation(heap());
3427 } 3455 }
3428 #endif 3456 #endif
3429 } 3457 }
3430 3458
3431 template <PointerDirection direction> 3459 template <PointerDirection direction>
3432 class PointerUpdateJobTraits { 3460 class PointerUpdateJobTraits {
3433 public: 3461 public:
3434 typedef int PerPageData; // Per page data is not used in this job. 3462 typedef int PerPageData; // Per page data is not used in this job.
3435 typedef PointersUpdatingVisitor* PerTaskData; 3463 typedef PointersUpdatingVisitor* PerTaskData;
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3602 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); 3630 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3603 p->ResetLiveBytes(); 3631 p->ResetLiveBytes();
3604 CHECK(p->SweepingDone()); 3632 CHECK(p->SweepingDone());
3605 space->ReleasePage(p); 3633 space->ReleasePage(p);
3606 } 3634 }
3607 evacuation_candidates_.Rewind(0); 3635 evacuation_candidates_.Rewind(0);
3608 compacting_ = false; 3636 compacting_ = false;
3609 heap()->FreeQueuedChunks(); 3637 heap()->FreeQueuedChunks();
3610 } 3638 }
3611 3639
3612 3640 int MarkCompactCollector::Sweeper::ParallelSweepSpace(AllocationSpace identity,
3613 int MarkCompactCollector::SweepInParallel(PagedSpace* space, 3641 int required_freed_bytes,
3614 int required_freed_bytes, 3642 int max_pages) {
3615 int max_pages) {
3616 int max_freed = 0; 3643 int max_freed = 0;
3617 int max_freed_overall = 0; 3644 int pages_freed = 0;
3618 int page_count = 0; 3645 ParallelSweepList(sweeping_list_[identity], identity, required_freed_bytes,
3619 for (Page* p : sweeping_list(space)) { 3646 max_pages, &max_freed, &pages_freed);
3620 max_freed = SweepInParallel(p, space); 3647 if ((required_freed_bytes) > 0 && (max_freed >= required_freed_bytes))
3621 DCHECK(max_freed >= 0); 3648 return max_freed;
3622 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { 3649 if ((max_pages > 0) && (pages_freed >= max_pages)) return max_freed;
3623 return max_freed; 3650 SweepingList* late_list = GetLateSweepingListSafe(identity);
3624 } 3651 if (late_list != nullptr) {
3625 max_freed_overall = Max(max_freed, max_freed_overall); 3652 ParallelSweepList(*late_list, identity, required_freed_bytes, max_pages,
3626 page_count++; 3653 &max_freed, &pages_freed);
3627 if (max_pages > 0 && page_count >= max_pages) {
3628 break;
3629 }
3630 } 3654 }
3631 return max_freed_overall; 3655 return max_freed;
3632 } 3656 }
3633 3657
3658 void MarkCompactCollector::Sweeper::ParallelSweepList(
3659 SweepingList& list, AllocationSpace out_space, int required_freed_bytes,
3660 int max_pages, int* max_freed, int* pages_freed) {
3661 for (Page* p : list) {
3662 int freed = ParallelSweepPage(p, heap_->paged_space(out_space));
3663 *pages_freed += 1;
3664 DCHECK_GE(freed, 0);
3665 *max_freed = Max(*max_freed, freed);
3666 if ((required_freed_bytes) > 0 && (*max_freed >= required_freed_bytes))
3667 return;
3668 if ((max_pages > 0) && (*pages_freed >= max_pages)) return;
3669 }
3670 }
3634 3671
3635 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { 3672 int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page,
3673 PagedSpace* space) {
3636 int max_freed = 0; 3674 int max_freed = 0;
3637 if (page->mutex()->TryLock()) { 3675 if (page->mutex()->TryLock()) {
3638 // If this page was already swept in the meantime, we can return here. 3676 // If this page was already swept in the meantime, we can return here.
3639 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { 3677 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) {
3640 page->mutex()->Unlock(); 3678 page->mutex()->Unlock();
3641 return 0; 3679 return 0;
3642 } 3680 }
3643 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); 3681 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
3644 if (space->identity() == OLD_SPACE) { 3682 if (space->identity() == OLD_SPACE) {
3645 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, 3683 max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
3646 IGNORE_FREE_SPACE>(space, page, NULL); 3684 IGNORE_FREE_SPACE>(space, page, NULL);
3647 } else if (space->identity() == CODE_SPACE) { 3685 } else if (space->identity() == CODE_SPACE) {
3648 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, 3686 max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST,
3649 IGNORE_FREE_SPACE>(space, page, NULL); 3687 IGNORE_FREE_SPACE>(space, page, NULL);
3650 } else { 3688 } else {
3651 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, 3689 max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
3652 IGNORE_FREE_SPACE>(space, page, NULL); 3690 IGNORE_FREE_SPACE>(space, page, NULL);
3653 } 3691 }
3654 { 3692 {
3655 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); 3693 base::LockGuard<base::Mutex> guard(&mutex_);
3656 swept_pages(space->identity())->Add(page); 3694 swept_list_[space->identity()].Add(page);
3657 } 3695 }
3658 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); 3696 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3659 page->mutex()->Unlock(); 3697 page->mutex()->Unlock();
3660 } 3698 }
3661 return max_freed; 3699 return max_freed;
3662 } 3700 }
3663 3701
3702 void MarkCompactCollector::Sweeper::AddPage(AllocationSpace space, Page* page) {
3703 DCHECK(!sweeping_in_progress_);
3704 PrepareToBeSweptPage(space, page);
3705 sweeping_list_[space].push_back(page);
3706 }
3707
3708 void MarkCompactCollector::Sweeper::AddLatePage(AllocationSpace space,
3709 Page* page) {
3710 DCHECK(sweeping_in_progress_);
3711 PrepareToBeSweptPage(space, page);
3712 if (tmp_late_sweeping_list_[space] == nullptr) {
3713 tmp_late_sweeping_list_[space] = new SweepingList();
3714 }
3715 tmp_late_sweeping_list_[space]->push_back(page);
3716 }
3717
3718 void MarkCompactCollector::Sweeper::PrepareToBeSweptPage(AllocationSpace space,
3719 Page* page) {
3720 page->concurrent_sweeping_state().SetValue(Page::kSweepingPending);
3721 int to_sweep = page->area_size() - page->LiveBytes();
3722 heap_->paged_space(space)->accounting_stats_.ShrinkSpace(to_sweep);
3723 }
3724
3725 void MarkCompactCollector::Sweeper::CommitLateList(AllocationSpace space) {
3726 DCHECK(sweeping_in_progress_);
3727 base::LockGuard<base::Mutex> guard(&mutex_);
3728 DCHECK_NULL(late_sweeping_list_[space]);
3729 late_sweeping_list_[space] = tmp_late_sweeping_list_[space];
3730 }
3731
3732 MarkCompactCollector::Sweeper::SweepingList*
3733 MarkCompactCollector::Sweeper::GetLateSweepingListSafe(AllocationSpace space) {
3734 base::LockGuard<base::Mutex> guard(&mutex_);
3735 return late_sweeping_list_[space];
3736 }
3664 3737
3665 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { 3738 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) {
3666 space->ClearStats(); 3739 space->ClearStats();
3667 3740
3668 PageIterator it(space); 3741 PageIterator it(space);
3669 3742
3670 int will_be_swept = 0; 3743 int will_be_swept = 0;
3671 bool unused_page_present = false; 3744 bool unused_page_present = false;
3672 3745
3673 while (it.has_next()) { 3746 while (it.has_next()) {
(...skipping 15 matching lines...) Expand all
3689 // TODO(hpayer): Free unused memory of last black page. 3762 // TODO(hpayer): Free unused memory of last black page.
3690 continue; 3763 continue;
3691 } 3764 }
3692 3765
3693 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { 3766 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) {
3694 // We need to sweep the page to get it into an iterable state again. Note 3767 // We need to sweep the page to get it into an iterable state again. Note
3695 // that this adds unusable memory into the free list that is later on 3768 // that this adds unusable memory into the free list that is later on
3696 // (in the free list) dropped again. Since we only use the flag for 3769 // (in the free list) dropped again. Since we only use the flag for
3697 // testing this is fine. 3770 // testing this is fine.
3698 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); 3771 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
3699 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, 3772 Sweeper::RawSweep<Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3700 IGNORE_FREE_SPACE>(space, p, nullptr); 3773 Sweeper::IGNORE_SKIP_LIST, Sweeper::IGNORE_FREE_SPACE>(
3774 space, p, nullptr);
3701 continue; 3775 continue;
3702 } 3776 }
3703 3777
3704 // One unused page is kept, all further are released before sweeping them. 3778 // One unused page is kept, all further are released before sweeping them.
3705 if (p->LiveBytes() == 0) { 3779 if (p->LiveBytes() == 0) {
3706 if (unused_page_present) { 3780 if (unused_page_present) {
3707 if (FLAG_gc_verbose) { 3781 if (FLAG_gc_verbose) {
3708 PrintIsolate(isolate(), "sweeping: released page: %p", p); 3782 PrintIsolate(isolate(), "sweeping: released page: %p", p);
3709 } 3783 }
3710 space->ReleasePage(p); 3784 space->ReleasePage(p);
3711 continue; 3785 continue;
3712 } 3786 }
3713 unused_page_present = true; 3787 unused_page_present = true;
3714 } 3788 }
3715 3789
3716 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); 3790 sweeper().AddPage(space->identity(), p);
3717 sweeping_list(space).push_back(p);
3718 int to_sweep = p->area_size() - p->LiveBytes();
3719 space->accounting_stats_.ShrinkSpace(to_sweep);
3720 will_be_swept++; 3791 will_be_swept++;
3721 } 3792 }
3722 3793
3723 if (FLAG_gc_verbose) { 3794 if (FLAG_gc_verbose) {
3724 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d", 3795 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d",
3725 AllocationSpaceName(space->identity()), will_be_swept); 3796 AllocationSpaceName(space->identity()), will_be_swept);
3726 } 3797 }
3727 std::sort(sweeping_list(space).begin(), sweeping_list(space).end(),
3728 [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); });
3729 } 3798 }
3730 3799
3731 3800
3732 void MarkCompactCollector::SweepSpaces() { 3801 void MarkCompactCollector::SweepSpaces() {
3733 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_SWEEP); 3802 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_SWEEP);
3734 double start_time = 0.0; 3803 double start_time = 0.0;
3735 if (FLAG_print_cumulative_gc_stat) { 3804 if (FLAG_print_cumulative_gc_stat) {
3736 start_time = heap_->MonotonicallyIncreasingTimeInMs(); 3805 start_time = heap_->MonotonicallyIncreasingTimeInMs();
3737 } 3806 }
3738 3807
3739 #ifdef DEBUG 3808 #ifdef DEBUG
3740 state_ = SWEEP_SPACES; 3809 state_ = SWEEP_SPACES;
3741 #endif 3810 #endif
3742 3811
3743 { 3812 {
3744 sweeping_in_progress_ = true;
3745 { 3813 {
3746 GCTracer::Scope sweep_scope(heap()->tracer(), 3814 GCTracer::Scope sweep_scope(heap()->tracer(),
3747 GCTracer::Scope::MC_SWEEP_OLD); 3815 GCTracer::Scope::MC_SWEEP_OLD);
3748 StartSweepSpace(heap()->old_space()); 3816 StartSweepSpace(heap()->old_space());
3749 } 3817 }
3750 { 3818 {
3751 GCTracer::Scope sweep_scope(heap()->tracer(), 3819 GCTracer::Scope sweep_scope(heap()->tracer(),
3752 GCTracer::Scope::MC_SWEEP_CODE); 3820 GCTracer::Scope::MC_SWEEP_CODE);
3753 StartSweepSpace(heap()->code_space()); 3821 StartSweepSpace(heap()->code_space());
3754 } 3822 }
3755 { 3823 {
3756 GCTracer::Scope sweep_scope(heap()->tracer(), 3824 GCTracer::Scope sweep_scope(heap()->tracer(),
3757 GCTracer::Scope::MC_SWEEP_MAP); 3825 GCTracer::Scope::MC_SWEEP_MAP);
3758 StartSweepSpace(heap()->map_space()); 3826 StartSweepSpace(heap()->map_space());
3759 } 3827 }
3760 if (FLAG_concurrent_sweeping) { 3828 sweeper().StartSweeping();
3761 StartSweeperThreads();
3762 }
3763 } 3829 }
3764 3830
3765 // Deallocate unmarked large objects. 3831 // Deallocate unmarked large objects.
3766 heap_->lo_space()->FreeUnmarkedObjects(); 3832 heap_->lo_space()->FreeUnmarkedObjects();
3767 3833
3768 if (FLAG_print_cumulative_gc_stat) { 3834 if (FLAG_print_cumulative_gc_stat) {
3769 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - 3835 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() -
3770 start_time); 3836 start_time);
3771 } 3837 }
3772 } 3838 }
3773 3839
3774
3775 void MarkCompactCollector::ParallelSweepSpacesComplete() {
3776 sweeping_list(heap()->old_space()).clear();
3777 sweeping_list(heap()->code_space()).clear();
3778 sweeping_list(heap()->map_space()).clear();
3779 }
3780
3781 Isolate* MarkCompactCollector::isolate() const { return heap_->isolate(); } 3840 Isolate* MarkCompactCollector::isolate() const { return heap_->isolate(); }
3782 3841
3783 3842
3784 void MarkCompactCollector::Initialize() { 3843 void MarkCompactCollector::Initialize() {
3785 MarkCompactMarkingVisitor::Initialize(); 3844 MarkCompactMarkingVisitor::Initialize();
3786 IncrementalMarking::Initialize(); 3845 IncrementalMarking::Initialize();
3787 } 3846 }
3788 3847
3789 void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* host, Address slot, 3848 void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* host, Address slot,
3790 Code* target) { 3849 Code* target) {
(...skipping 15 matching lines...) Expand all
3806 MarkBit mark_bit = Marking::MarkBitFrom(host); 3865 MarkBit mark_bit = Marking::MarkBitFrom(host);
3807 if (Marking::IsBlack(mark_bit)) { 3866 if (Marking::IsBlack(mark_bit)) {
3808 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 3867 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
3809 RecordRelocSlot(host, &rinfo, target); 3868 RecordRelocSlot(host, &rinfo, target);
3810 } 3869 }
3811 } 3870 }
3812 } 3871 }
3813 3872
3814 } // namespace internal 3873 } // namespace internal
3815 } // namespace v8 3874 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/mark-compact-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698