| OLD | NEW |
| 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 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 } | 440 } |
| 441 | 441 |
| 442 return compacting_; | 442 return compacting_; |
| 443 } | 443 } |
| 444 | 444 |
| 445 void MarkCompactCollector::CollectGarbage() { | 445 void MarkCompactCollector::CollectGarbage() { |
| 446 // Make sure that Prepare() has been called. The individual steps below will | 446 // Make sure that Prepare() has been called. The individual steps below will |
| 447 // update the state as they proceed. | 447 // update the state as they proceed. |
| 448 DCHECK(state_ == PREPARE_GC); | 448 DCHECK(state_ == PREPARE_GC); |
| 449 | 449 |
| 450 heap()->minor_mark_compact_collector()->CleanupSweepToIteratePages(); |
| 451 |
| 450 MarkLiveObjects(); | 452 MarkLiveObjects(); |
| 451 | 453 |
| 452 DCHECK(heap_->incremental_marking()->IsStopped()); | 454 DCHECK(heap_->incremental_marking()->IsStopped()); |
| 453 | 455 |
| 454 ClearNonLiveReferences(); | 456 ClearNonLiveReferences(); |
| 455 | 457 |
| 456 RecordObjectStats(); | 458 RecordObjectStats(); |
| 457 | 459 |
| 458 #ifdef VERIFY_HEAP | 460 #ifdef VERIFY_HEAP |
| 459 if (FLAG_verify_heap) { | 461 if (FLAG_verify_heap) { |
| (...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 heap()->isolate()->thread_manager()->IterateArchivedThreads( | 1453 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
| 1452 &code_marking_visitor); | 1454 &code_marking_visitor); |
| 1453 | 1455 |
| 1454 SharedFunctionInfoMarkingVisitor visitor(this); | 1456 SharedFunctionInfoMarkingVisitor visitor(this); |
| 1455 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); | 1457 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); |
| 1456 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); | 1458 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); |
| 1457 | 1459 |
| 1458 ProcessMarkingDeque(); | 1460 ProcessMarkingDeque(); |
| 1459 } | 1461 } |
| 1460 | 1462 |
| 1463 void MinorMarkCompactCollector::CleanupSweepToIteratePages() { |
| 1464 for (Page* p : sweep_to_iterate_pages_) { |
| 1465 if (p->IsFlagSet(Page::SWEEP_TO_ITERATE)) { |
| 1466 p->ClearFlag(Page::SWEEP_TO_ITERATE); |
| 1467 marking_state(p).ClearLiveness(); |
| 1468 } |
| 1469 } |
| 1470 sweep_to_iterate_pages_.clear(); |
| 1471 } |
| 1472 |
| 1461 class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor { | 1473 class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor { |
| 1462 public: | 1474 public: |
| 1463 explicit RootMarkingVisitor(MinorMarkCompactCollector* collector) | 1475 explicit RootMarkingVisitor(MinorMarkCompactCollector* collector) |
| 1464 : collector_(collector) {} | 1476 : collector_(collector) {} |
| 1465 | 1477 |
| 1466 void VisitRootPointer(Root root, Object** p) override { | 1478 void VisitRootPointer(Root root, Object** p) override { |
| 1467 MarkObjectByPointer(p); | 1479 MarkObjectByPointer(p); |
| 1468 } | 1480 } |
| 1469 | 1481 |
| 1470 void VisitRootPointers(Root root, Object** start, Object** end) override { | 1482 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| (...skipping 1110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2581 Map* map = object->map(); | 2593 Map* map = object->map(); |
| 2582 DCHECK((ObjectMarking::IsBlack<MarkBit::NON_ATOMIC>( | 2594 DCHECK((ObjectMarking::IsBlack<MarkBit::NON_ATOMIC>( |
| 2583 object, MarkingState::External(object)))); | 2595 object, MarkingState::External(object)))); |
| 2584 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); | 2596 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); |
| 2585 } | 2597 } |
| 2586 } | 2598 } |
| 2587 | 2599 |
| 2588 void MinorMarkCompactCollector::CollectGarbage() { | 2600 void MinorMarkCompactCollector::CollectGarbage() { |
| 2589 heap()->mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); | 2601 heap()->mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); |
| 2590 | 2602 |
| 2603 CleanupSweepToIteratePages(); |
| 2604 |
| 2591 MarkLiveObjects(); | 2605 MarkLiveObjects(); |
| 2592 ClearNonLiveReferences(); | 2606 ClearNonLiveReferences(); |
| 2593 #ifdef VERIFY_HEAP | 2607 #ifdef VERIFY_HEAP |
| 2594 if (FLAG_verify_heap) { | 2608 if (FLAG_verify_heap) { |
| 2595 YoungGenerationMarkingVerifier verifier(heap()); | 2609 YoungGenerationMarkingVerifier verifier(heap()); |
| 2596 verifier.Run(); | 2610 verifier.Run(); |
| 2597 } | 2611 } |
| 2598 #endif // VERIFY_HEAP | 2612 #endif // VERIFY_HEAP |
| 2599 | 2613 |
| 2600 Evacuate(); | 2614 Evacuate(); |
| 2601 #ifdef VERIFY_HEAP | 2615 #ifdef VERIFY_HEAP |
| 2602 if (FLAG_verify_heap) { | 2616 if (FLAG_verify_heap) { |
| 2603 YoungGenerationEvacuationVerifier verifier(heap()); | 2617 YoungGenerationEvacuationVerifier verifier(heap()); |
| 2604 verifier.Run(); | 2618 verifier.Run(); |
| 2605 } | 2619 } |
| 2606 #endif // VERIFY_HEAP | 2620 #endif // VERIFY_HEAP |
| 2607 | 2621 |
| 2608 heap()->incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 2622 heap()->incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
| 2609 | 2623 |
| 2610 { | 2624 { |
| 2611 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_CLEAR_LIVENESS); | 2625 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_CLEAR_LIVENESS); |
| 2612 for (Page* p : PageRange(heap()->new_space()->FromSpaceStart(), | 2626 for (Page* p : PageRange(heap()->new_space()->FromSpaceStart(), |
| 2613 heap()->new_space()->FromSpaceEnd())) { | 2627 heap()->new_space()->FromSpaceEnd())) { |
| 2628 DCHECK(!p->IsFlagSet(Page::SWEEP_TO_ITERATE)); |
| 2614 marking_state(p).ClearLiveness(); | 2629 marking_state(p).ClearLiveness(); |
| 2615 } | 2630 } |
| 2616 } | 2631 } |
| 2617 | 2632 |
| 2618 heap()->account_external_memory_concurrently_freed(); | 2633 heap()->account_external_memory_concurrently_freed(); |
| 2619 } | 2634 } |
| 2620 | 2635 |
| 2636 void MinorMarkCompactCollector::MakeIterable( |
| 2637 Page* p, MarkingTreatmentMode marking_mode, |
| 2638 FreeSpaceTreatmentMode free_space_mode) { |
| 2639 // We have to clear the full collectors markbits for the areas that we |
| 2640 // remove here. |
| 2641 MarkCompactCollector* full_collector = heap()->mark_compact_collector(); |
| 2642 Address free_start = p->area_start(); |
| 2643 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 2644 LiveObjectIterator<kBlackObjects> it(p, marking_state(p)); |
| 2645 HeapObject* object = nullptr; |
| 2646 |
| 2647 while ((object = it.Next()) != nullptr) { |
| 2648 DCHECK(ObjectMarking::IsBlack(object, marking_state(object))); |
| 2649 Address free_end = object->address(); |
| 2650 if (free_end != free_start) { |
| 2651 CHECK_GT(free_end, free_start); |
| 2652 size_t size = static_cast<size_t>(free_end - free_start); |
| 2653 if (free_space_mode == ZAP_FREE_SPACE) { |
| 2654 memset(free_start, 0xcc, size); |
| 2655 full_collector->marking_state(p).bitmap()->ClearRange( |
| 2656 p->AddressToMarkbitIndex(free_start), |
| 2657 p->AddressToMarkbitIndex(free_end)); |
| 2658 } |
| 2659 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), |
| 2660 ClearRecordedSlots::kNo); |
| 2661 } |
| 2662 Map* map = object->synchronized_map(); |
| 2663 int size = object->SizeFromMap(map); |
| 2664 free_start = free_end + size; |
| 2665 } |
| 2666 |
| 2667 if (free_start != p->area_end()) { |
| 2668 CHECK_GT(p->area_end(), free_start); |
| 2669 size_t size = static_cast<size_t>(p->area_end() - free_start); |
| 2670 if (free_space_mode == ZAP_FREE_SPACE) { |
| 2671 memset(free_start, 0xcc, size); |
| 2672 full_collector->marking_state(p).bitmap()->ClearRange( |
| 2673 p->AddressToMarkbitIndex(free_start), |
| 2674 p->AddressToMarkbitIndex(p->area_end())); |
| 2675 } |
| 2676 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), |
| 2677 ClearRecordedSlots::kNo); |
| 2678 } |
| 2679 |
| 2680 if (marking_mode == MarkingTreatmentMode::CLEAR) { |
| 2681 marking_state(p).ClearLiveness(); |
| 2682 p->ClearFlag(Page::SWEEP_TO_ITERATE); |
| 2683 } |
| 2684 } |
| 2685 |
| 2621 void MinorMarkCompactCollector::ClearNonLiveReferences() { | 2686 void MinorMarkCompactCollector::ClearNonLiveReferences() { |
| 2622 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | 2687 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
| 2623 | 2688 |
| 2624 { | 2689 { |
| 2625 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); | 2690 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
| 2626 // Internalized strings are always stored in old space, so there is no need | 2691 // Internalized strings are always stored in old space, so there is no need |
| 2627 // to clean them here. | 2692 // to clean them here. |
| 2628 YoungGenerationExternalStringTableCleaner external_visitor(*this); | 2693 YoungGenerationExternalStringTableCleaner external_visitor(*this); |
| 2629 heap()->external_string_table_.IterateNewSpaceStrings(&external_visitor); | 2694 heap()->external_string_table_.IterateNewSpaceStrings(&external_visitor); |
| 2630 heap()->external_string_table_.CleanUpNewSpaceStrings(); | 2695 heap()->external_string_table_.CleanUpNewSpaceStrings(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2673 if (!heap()->new_space()->Rebalance()) { | 2738 if (!heap()->new_space()->Rebalance()) { |
| 2674 FatalProcessOutOfMemory("NewSpace::Rebalance"); | 2739 FatalProcessOutOfMemory("NewSpace::Rebalance"); |
| 2675 } | 2740 } |
| 2676 } | 2741 } |
| 2677 | 2742 |
| 2678 // Give pages that are queued to be freed back to the OS. | 2743 // Give pages that are queued to be freed back to the OS. |
| 2679 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); | 2744 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); |
| 2680 | 2745 |
| 2681 { | 2746 { |
| 2682 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP); | 2747 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP); |
| 2683 // TODO(mlippautz): Implement page promotion. | 2748 for (Page* p : new_space_evacuation_pages_) { |
| 2749 if (p->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION) || |
| 2750 p->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)) { |
| 2751 p->ClearFlag(Page::PAGE_NEW_NEW_PROMOTION); |
| 2752 p->ClearFlag(Page::PAGE_NEW_OLD_PROMOTION); |
| 2753 p->SetFlag(Page::SWEEP_TO_ITERATE); |
| 2754 sweep_to_iterate_pages_.push_back(p); |
| 2755 } |
| 2756 } |
| 2684 new_space_evacuation_pages_.Rewind(0); | 2757 new_space_evacuation_pages_.Rewind(0); |
| 2685 } | 2758 } |
| 2686 | 2759 |
| 2687 { | 2760 { |
| 2688 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_EPILOGUE); | 2761 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_EPILOGUE); |
| 2689 EvacuateEpilogue(); | 2762 EvacuateEpilogue(); |
| 2690 } | 2763 } |
| 2691 } | 2764 } |
| 2692 | 2765 |
| 2693 void MarkCompactCollector::MarkLiveObjects() { | 2766 void MarkCompactCollector::MarkLiveObjects() { |
| (...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3564 *live_bytes = state.live_bytes(); | 3637 *live_bytes = state.live_bytes(); |
| 3565 switch (ComputeEvacuationMode(page)) { | 3638 switch (ComputeEvacuationMode(page)) { |
| 3566 case kObjectsNewToOld: | 3639 case kObjectsNewToOld: |
| 3567 success = object_visitor.VisitBlackObjects( | 3640 success = object_visitor.VisitBlackObjects( |
| 3568 page, state, &new_space_visitor_, LiveObjectVisitor::kClearMarkbits); | 3641 page, state, &new_space_visitor_, LiveObjectVisitor::kClearMarkbits); |
| 3569 DCHECK(success); | 3642 DCHECK(success); |
| 3570 ArrayBufferTracker::ProcessBuffers( | 3643 ArrayBufferTracker::ProcessBuffers( |
| 3571 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); | 3644 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
| 3572 break; | 3645 break; |
| 3573 case kPageNewToOld: | 3646 case kPageNewToOld: |
| 3574 // TODO(mlippautz): Implement page promotion. | 3647 success = object_visitor.VisitBlackObjects( |
| 3575 UNREACHABLE(); | 3648 page, state, &new_to_old_page_visitor_, |
| 3649 LiveObjectVisitor::kKeepMarking); |
| 3650 DCHECK(success); |
| 3651 new_to_old_page_visitor_.account_moved_bytes(state.live_bytes()); |
| 3652 // TODO(mlippautz): If cleaning array buffers is too slow here we can |
| 3653 // delay it until the next GC. |
| 3654 ArrayBufferTracker::FreeDead(page, state); |
| 3655 if (heap()->ShouldZapGarbage()) |
| 3656 collector_->MakeIterable(page, MarkingTreatmentMode::KEEP, |
| 3657 ZAP_FREE_SPACE); |
| 3576 break; | 3658 break; |
| 3577 case kPageNewToNew: | 3659 case kPageNewToNew: |
| 3578 // TODO(mlippautz): Implement page promotion. | 3660 success = object_visitor.VisitBlackObjects( |
| 3579 UNREACHABLE(); | 3661 page, state, &new_to_new_page_visitor_, |
| 3662 LiveObjectVisitor::kKeepMarking); |
| 3663 DCHECK(success); |
| 3664 new_to_new_page_visitor_.account_moved_bytes(state.live_bytes()); |
| 3665 // TODO(mlippautz): If cleaning array buffers is too slow here we can |
| 3666 // delay it until the next GC. |
| 3667 ArrayBufferTracker::FreeDead(page, state); |
| 3668 if (heap()->ShouldZapGarbage()) |
| 3669 collector_->MakeIterable(page, MarkingTreatmentMode::KEEP, |
| 3670 ZAP_FREE_SPACE); |
| 3580 break; | 3671 break; |
| 3581 case kObjectsOldToOld: | 3672 case kObjectsOldToOld: |
| 3582 UNREACHABLE(); | 3673 UNREACHABLE(); |
| 3583 break; | 3674 break; |
| 3584 } | 3675 } |
| 3585 return success; | 3676 return success; |
| 3586 } | 3677 } |
| 3587 | 3678 |
| 3588 class EvacuationJobTraits { | 3679 class EvacuationJobTraits { |
| 3589 public: | 3680 public: |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3682 "aborted=%d wanted_tasks=%d tasks=%d cores=%" PRIuS | 3773 "aborted=%d wanted_tasks=%d tasks=%d cores=%" PRIuS |
| 3683 " live_bytes=%" V8PRIdPTR " compaction_speed=%.f\n", | 3774 " live_bytes=%" V8PRIdPTR " compaction_speed=%.f\n", |
| 3684 isolate()->time_millis_since_init(), | 3775 isolate()->time_millis_since_init(), |
| 3685 FLAG_parallel_compaction ? "yes" : "no", job->NumberOfPages(), | 3776 FLAG_parallel_compaction ? "yes" : "no", job->NumberOfPages(), |
| 3686 abandoned_pages, wanted_num_tasks, job->NumberOfTasks(), | 3777 abandoned_pages, wanted_num_tasks, job->NumberOfTasks(), |
| 3687 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(), | 3778 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(), |
| 3688 live_bytes, compaction_speed); | 3779 live_bytes, compaction_speed); |
| 3689 } | 3780 } |
| 3690 } | 3781 } |
| 3691 | 3782 |
| 3783 bool MarkCompactCollectorBase::ShouldMovePage(Page* p, intptr_t live_bytes) { |
| 3784 const bool reduce_memory = heap()->ShouldReduceMemory(); |
| 3785 const Address age_mark = heap()->new_space()->age_mark(); |
| 3786 return !reduce_memory && !p->NeverEvacuate() && |
| 3787 (live_bytes > Evacuator::PageEvacuationThreshold()) && |
| 3788 !p->Contains(age_mark) && heap()->CanExpandOldGeneration(live_bytes); |
| 3789 } |
| 3790 |
| 3692 void MarkCompactCollector::EvacuatePagesInParallel() { | 3791 void MarkCompactCollector::EvacuatePagesInParallel() { |
| 3693 PageParallelJob<EvacuationJobTraits> job( | 3792 PageParallelJob<EvacuationJobTraits> job( |
| 3694 heap_, heap_->isolate()->cancelable_task_manager(), | 3793 heap_, heap_->isolate()->cancelable_task_manager(), |
| 3695 &page_parallel_job_semaphore_); | 3794 &page_parallel_job_semaphore_); |
| 3696 | 3795 |
| 3697 int abandoned_pages = 0; | 3796 int abandoned_pages = 0; |
| 3698 intptr_t live_bytes = 0; | 3797 intptr_t live_bytes = 0; |
| 3699 for (Page* page : old_space_evacuation_pages_) { | 3798 for (Page* page : old_space_evacuation_pages_) { |
| 3700 live_bytes += MarkingState::Internal(page).live_bytes(); | 3799 live_bytes += MarkingState::Internal(page).live_bytes(); |
| 3701 job.AddPage(page, {&abandoned_pages, marking_state(page)}); | 3800 job.AddPage(page, {&abandoned_pages, marking_state(page)}); |
| 3702 } | 3801 } |
| 3703 | 3802 |
| 3704 const bool reduce_memory = heap()->ShouldReduceMemory(); | |
| 3705 const Address age_mark = heap()->new_space()->age_mark(); | |
| 3706 for (Page* page : new_space_evacuation_pages_) { | 3803 for (Page* page : new_space_evacuation_pages_) { |
| 3707 intptr_t live_bytes_on_page = MarkingState::Internal(page).live_bytes(); | 3804 intptr_t live_bytes_on_page = MarkingState::Internal(page).live_bytes(); |
| 3708 live_bytes += live_bytes_on_page; | 3805 live_bytes += live_bytes_on_page; |
| 3709 if (!reduce_memory && !page->NeverEvacuate() && | 3806 if (ShouldMovePage(page, live_bytes_on_page)) { |
| 3710 (live_bytes_on_page > Evacuator::PageEvacuationThreshold()) && | |
| 3711 !page->Contains(age_mark) && | |
| 3712 heap()->CanExpandOldGeneration(live_bytes_on_page)) { | |
| 3713 if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) { | 3807 if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) { |
| 3714 EvacuateNewSpacePageVisitor<NEW_TO_OLD>::Move(page); | 3808 EvacuateNewSpacePageVisitor<NEW_TO_OLD>::Move(page); |
| 3715 } else { | 3809 } else { |
| 3716 EvacuateNewSpacePageVisitor<NEW_TO_NEW>::Move(page); | 3810 EvacuateNewSpacePageVisitor<NEW_TO_NEW>::Move(page); |
| 3717 } | 3811 } |
| 3718 } | 3812 } |
| 3719 | |
| 3720 job.AddPage(page, {&abandoned_pages, marking_state(page)}); | 3813 job.AddPage(page, {&abandoned_pages, marking_state(page)}); |
| 3721 } | 3814 } |
| 3722 DCHECK_GE(job.NumberOfPages(), 1); | 3815 DCHECK_GE(job.NumberOfPages(), 1); |
| 3723 | 3816 |
| 3724 RecordMigratedSlotVisitor record_visitor(this); | 3817 RecordMigratedSlotVisitor record_visitor(this); |
| 3725 CreateAndExecuteEvacuationTasks<FullEvacuator>( | 3818 CreateAndExecuteEvacuationTasks<FullEvacuator>( |
| 3726 this, &job, &record_visitor, nullptr, live_bytes, abandoned_pages); | 3819 this, &job, &record_visitor, nullptr, live_bytes, abandoned_pages); |
| 3727 } | 3820 } |
| 3728 | 3821 |
| 3729 void MinorMarkCompactCollector::EvacuatePagesInParallel() { | 3822 void MinorMarkCompactCollector::EvacuatePagesInParallel() { |
| 3730 PageParallelJob<EvacuationJobTraits> job( | 3823 PageParallelJob<EvacuationJobTraits> job( |
| 3731 heap_, heap_->isolate()->cancelable_task_manager(), | 3824 heap_, heap_->isolate()->cancelable_task_manager(), |
| 3732 &page_parallel_job_semaphore_); | 3825 &page_parallel_job_semaphore_); |
| 3733 int abandoned_pages = 0; | 3826 int abandoned_pages = 0; |
| 3734 intptr_t live_bytes = 0; | 3827 intptr_t live_bytes = 0; |
| 3735 | 3828 |
| 3736 for (Page* page : new_space_evacuation_pages_) { | 3829 for (Page* page : new_space_evacuation_pages_) { |
| 3737 intptr_t live_bytes_on_page = marking_state(page).live_bytes(); | 3830 intptr_t live_bytes_on_page = marking_state(page).live_bytes(); |
| 3738 live_bytes += live_bytes_on_page; | 3831 live_bytes += live_bytes_on_page; |
| 3739 // TODO(mlippautz): Implement page promotion. | 3832 if (ShouldMovePage(page, live_bytes_on_page)) { |
| 3833 if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) { |
| 3834 EvacuateNewSpacePageVisitor<NEW_TO_OLD>::Move(page); |
| 3835 } else { |
| 3836 EvacuateNewSpacePageVisitor<NEW_TO_NEW>::Move(page); |
| 3837 } |
| 3838 } |
| 3740 job.AddPage(page, {&abandoned_pages, marking_state(page)}); | 3839 job.AddPage(page, {&abandoned_pages, marking_state(page)}); |
| 3741 } | 3840 } |
| 3742 DCHECK_GE(job.NumberOfPages(), 1); | 3841 DCHECK_GE(job.NumberOfPages(), 1); |
| 3743 | 3842 |
| 3744 YoungGenerationMigrationObserver observer(heap(), | 3843 YoungGenerationMigrationObserver observer(heap(), |
| 3745 heap()->mark_compact_collector()); | 3844 heap()->mark_compact_collector()); |
| 3746 YoungGenerationRecordMigratedSlotVisitor record_visitor( | 3845 YoungGenerationRecordMigratedSlotVisitor record_visitor( |
| 3747 heap()->mark_compact_collector()); | 3846 heap()->mark_compact_collector()); |
| 3748 CreateAndExecuteEvacuationTasks<YoungGenerationEvacuator>( | 3847 CreateAndExecuteEvacuationTasks<YoungGenerationEvacuator>( |
| 3749 this, &job, &record_visitor, &observer, live_bytes, abandoned_pages); | 3848 this, &job, &record_visitor, &observer, live_bytes, abandoned_pages); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4053 FullEvacuationVerifier verifier(heap()); | 4152 FullEvacuationVerifier verifier(heap()); |
| 4054 verifier.Run(); | 4153 verifier.Run(); |
| 4055 } | 4154 } |
| 4056 #endif | 4155 #endif |
| 4057 } | 4156 } |
| 4058 | 4157 |
| 4059 template <RememberedSetType type> | 4158 template <RememberedSetType type> |
| 4060 class PointerUpdateJobTraits { | 4159 class PointerUpdateJobTraits { |
| 4061 public: | 4160 public: |
| 4062 typedef int PerPageData; // Per page data is not used in this job. | 4161 typedef int PerPageData; // Per page data is not used in this job. |
| 4063 typedef int PerTaskData; // Per task data is not used in this job. | 4162 typedef const MarkCompactCollectorBase* PerTaskData; |
| 4064 | 4163 |
| 4065 static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk, | 4164 static bool ProcessPageInParallel(Heap* heap, PerTaskData task_data, |
| 4066 PerPageData) { | 4165 MemoryChunk* chunk, PerPageData) { |
| 4067 UpdateUntypedPointers(heap, chunk); | 4166 UpdateUntypedPointers(heap, chunk, task_data); |
| 4068 UpdateTypedPointers(heap, chunk); | 4167 UpdateTypedPointers(heap, chunk, task_data); |
| 4069 return true; | 4168 return true; |
| 4070 } | 4169 } |
| 4071 static const bool NeedSequentialFinalization = false; | 4170 static const bool NeedSequentialFinalization = false; |
| 4072 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { | 4171 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { |
| 4073 } | 4172 } |
| 4074 | 4173 |
| 4075 private: | 4174 private: |
| 4076 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { | 4175 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk, |
| 4176 const MarkCompactCollectorBase* collector) { |
| 4077 base::LockGuard<base::RecursiveMutex> guard(chunk->mutex()); | 4177 base::LockGuard<base::RecursiveMutex> guard(chunk->mutex()); |
| 4078 if (type == OLD_TO_NEW) { | 4178 if (type == OLD_TO_NEW) { |
| 4079 RememberedSet<OLD_TO_NEW>::Iterate(chunk, [heap](Address slot) { | 4179 RememberedSet<OLD_TO_NEW>::Iterate( |
| 4080 return CheckAndUpdateOldToNewSlot(heap, slot); | 4180 chunk, [heap, collector](Address slot) { |
| 4081 }); | 4181 return CheckAndUpdateOldToNewSlot(heap, slot, collector); |
| 4182 }); |
| 4082 } else { | 4183 } else { |
| 4083 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) { | 4184 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) { |
| 4084 return UpdateSlot(reinterpret_cast<Object**>(slot)); | 4185 return UpdateSlot(reinterpret_cast<Object**>(slot)); |
| 4085 }); | 4186 }); |
| 4086 } | 4187 } |
| 4087 } | 4188 } |
| 4088 | 4189 |
| 4089 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { | 4190 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk, |
| 4191 const MarkCompactCollectorBase* collector) { |
| 4090 if (type == OLD_TO_OLD) { | 4192 if (type == OLD_TO_OLD) { |
| 4091 Isolate* isolate = heap->isolate(); | 4193 Isolate* isolate = heap->isolate(); |
| 4092 RememberedSet<OLD_TO_OLD>::IterateTyped( | 4194 RememberedSet<OLD_TO_OLD>::IterateTyped( |
| 4093 chunk, | 4195 chunk, |
| 4094 [isolate](SlotType slot_type, Address host_addr, Address slot) { | 4196 [isolate](SlotType slot_type, Address host_addr, Address slot) { |
| 4095 return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, slot_type, | 4197 return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, slot_type, |
| 4096 slot, UpdateSlot); | 4198 slot, UpdateSlot); |
| 4097 }); | 4199 }); |
| 4098 } else { | 4200 } else { |
| 4099 Isolate* isolate = heap->isolate(); | 4201 Isolate* isolate = heap->isolate(); |
| 4100 RememberedSet<OLD_TO_NEW>::IterateTyped( | 4202 RememberedSet<OLD_TO_NEW>::IterateTyped( |
| 4101 chunk, | 4203 chunk, [isolate, heap, collector](SlotType slot_type, |
| 4102 [isolate, heap](SlotType slot_type, Address host_addr, Address slot) { | 4204 Address host_addr, Address slot) { |
| 4103 return UpdateTypedSlotHelper::UpdateTypedSlot( | 4205 return UpdateTypedSlotHelper::UpdateTypedSlot( |
| 4104 isolate, slot_type, slot, [heap](Object** slot) { | 4206 isolate, slot_type, slot, [heap, collector](Object** slot) { |
| 4105 return CheckAndUpdateOldToNewSlot( | 4207 return CheckAndUpdateOldToNewSlot( |
| 4106 heap, reinterpret_cast<Address>(slot)); | 4208 heap, reinterpret_cast<Address>(slot), collector); |
| 4107 }); | 4209 }); |
| 4108 }); | 4210 }); |
| 4109 } | 4211 } |
| 4110 } | 4212 } |
| 4111 | 4213 |
| 4112 static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap, | 4214 static SlotCallbackResult CheckAndUpdateOldToNewSlot( |
| 4113 Address slot_address) { | 4215 Heap* heap, Address slot_address, |
| 4216 const MarkCompactCollectorBase* collector) { |
| 4114 // There may be concurrent action on slots in dead objects. Concurrent | 4217 // There may be concurrent action on slots in dead objects. Concurrent |
| 4115 // sweeper threads may overwrite the slot content with a free space object. | 4218 // sweeper threads may overwrite the slot content with a free space object. |
| 4116 // Moreover, the pointed-to object may also get concurrently overwritten | 4219 // Moreover, the pointed-to object may also get concurrently overwritten |
| 4117 // with a free space object. The sweeper always gets priority performing | 4220 // with a free space object. The sweeper always gets priority performing |
| 4118 // these writes. | 4221 // these writes. |
| 4119 base::NoBarrierAtomicValue<Object*>* slot = | 4222 base::NoBarrierAtomicValue<Object*>* slot = |
| 4120 base::NoBarrierAtomicValue<Object*>::FromAddress(slot_address); | 4223 base::NoBarrierAtomicValue<Object*>::FromAddress(slot_address); |
| 4121 Object* slot_reference = slot->Value(); | 4224 Object* slot_reference = slot->Value(); |
| 4122 if (heap->InFromSpace(slot_reference)) { | 4225 if (heap->InFromSpace(slot_reference)) { |
| 4123 HeapObject* heap_object = reinterpret_cast<HeapObject*>(slot_reference); | 4226 HeapObject* heap_object = reinterpret_cast<HeapObject*>(slot_reference); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4143 if (heap->InToSpace(slot->Value())) { | 4246 if (heap->InToSpace(slot->Value())) { |
| 4144 return KEEP_SLOT; | 4247 return KEEP_SLOT; |
| 4145 } | 4248 } |
| 4146 } else if (heap->InToSpace(slot_reference)) { | 4249 } else if (heap->InToSpace(slot_reference)) { |
| 4147 // Slots can point to "to" space if the page has been moved, or if the | 4250 // Slots can point to "to" space if the page has been moved, or if the |
| 4148 // slot has been recorded multiple times in the remembered set. Since | 4251 // slot has been recorded multiple times in the remembered set. Since |
| 4149 // there is no forwarding information present we need to check the | 4252 // there is no forwarding information present we need to check the |
| 4150 // markbits to determine liveness. | 4253 // markbits to determine liveness. |
| 4151 HeapObject* heap_object = reinterpret_cast<HeapObject*>(slot_reference); | 4254 HeapObject* heap_object = reinterpret_cast<HeapObject*>(slot_reference); |
| 4152 if (ObjectMarking::IsBlack(heap_object, | 4255 if (ObjectMarking::IsBlack(heap_object, |
| 4153 MarkingState::Internal(heap_object))) | 4256 collector->marking_state(heap_object))) |
| 4154 return KEEP_SLOT; | 4257 return KEEP_SLOT; |
| 4155 } else { | 4258 } else { |
| 4156 DCHECK(!heap->InNewSpace(slot_reference)); | 4259 DCHECK(!heap->InNewSpace(slot_reference)); |
| 4157 } | 4260 } |
| 4158 return REMOVE_SLOT; | 4261 return REMOVE_SLOT; |
| 4159 } | 4262 } |
| 4160 }; | 4263 }; |
| 4161 | 4264 |
| 4162 int NumberOfPointerUpdateTasks(int pages) { | 4265 int NumberOfPointerUpdateTasks(int pages) { |
| 4163 if (!FLAG_parallel_pointer_update) return 1; | 4266 if (!FLAG_parallel_pointer_update) return 1; |
| 4164 const int available_cores = Max( | 4267 const int available_cores = Max( |
| 4165 1, static_cast<int>( | 4268 1, static_cast<int>( |
| 4166 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); | 4269 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
| 4167 const int kPagesPerTask = 4; | 4270 const int kPagesPerTask = 4; |
| 4168 return Min(available_cores, (pages + kPagesPerTask - 1) / kPagesPerTask); | 4271 return Min(available_cores, (pages + kPagesPerTask - 1) / kPagesPerTask); |
| 4169 } | 4272 } |
| 4170 | 4273 |
| 4171 template <RememberedSetType type> | 4274 template <RememberedSetType type> |
| 4172 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore) { | 4275 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore, |
| 4276 const MarkCompactCollectorBase* collector) { |
| 4173 PageParallelJob<PointerUpdateJobTraits<type> > job( | 4277 PageParallelJob<PointerUpdateJobTraits<type> > job( |
| 4174 heap, heap->isolate()->cancelable_task_manager(), semaphore); | 4278 heap, heap->isolate()->cancelable_task_manager(), semaphore); |
| 4175 RememberedSet<type>::IterateMemoryChunks( | 4279 RememberedSet<type>::IterateMemoryChunks( |
| 4176 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); | 4280 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); |
| 4177 int num_pages = job.NumberOfPages(); | 4281 int num_pages = job.NumberOfPages(); |
| 4178 int num_tasks = NumberOfPointerUpdateTasks(num_pages); | 4282 int num_tasks = NumberOfPointerUpdateTasks(num_pages); |
| 4179 job.Run(num_tasks, [](int i) { return 0; }); | 4283 job.Run(num_tasks, [collector](int i) { return collector; }); |
| 4180 } | 4284 } |
| 4181 | 4285 |
| 4182 class ToSpacePointerUpdateJobTraits { | 4286 class ToSpacePointerUpdateJobTraits { |
| 4183 public: | 4287 public: |
| 4184 struct PageData { | 4288 struct PageData { |
| 4185 Address start; | 4289 Address start; |
| 4186 Address end; | 4290 Address end; |
| 4187 MarkingState marking_state; | 4291 MarkingState marking_state; |
| 4188 }; | 4292 }; |
| 4189 | 4293 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4256 | 4360 |
| 4257 | 4361 |
| 4258 { | 4362 { |
| 4259 TRACE_GC(heap()->tracer(), | 4363 TRACE_GC(heap()->tracer(), |
| 4260 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 4364 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 4261 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_, | 4365 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_, |
| 4262 *this); | 4366 *this); |
| 4263 // Update roots. | 4367 // Update roots. |
| 4264 PointersUpdatingVisitor updating_visitor; | 4368 PointersUpdatingVisitor updating_visitor; |
| 4265 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 4369 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 4266 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); | 4370 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_, |
| 4371 this); |
| 4267 } | 4372 } |
| 4268 | 4373 |
| 4269 { | 4374 { |
| 4270 Heap* heap = this->heap(); | 4375 Heap* heap = this->heap(); |
| 4271 TRACE_GC(heap->tracer(), | 4376 TRACE_GC(heap->tracer(), |
| 4272 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); | 4377 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
| 4273 UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_); | 4378 UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_, |
| 4379 this); |
| 4274 } | 4380 } |
| 4275 | 4381 |
| 4276 { | 4382 { |
| 4277 TRACE_GC(heap()->tracer(), | 4383 TRACE_GC(heap()->tracer(), |
| 4278 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); | 4384 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
| 4279 // Update pointers from external string table. | 4385 // Update pointers from external string table. |
| 4280 heap_->UpdateReferencesInExternalStringTable( | 4386 heap_->UpdateReferencesInExternalStringTable( |
| 4281 &UpdateReferenceInExternalStringTableEntry); | 4387 &UpdateReferenceInExternalStringTableEntry); |
| 4282 | 4388 |
| 4283 EvacuationWeakObjectRetainer evacuation_object_retainer; | 4389 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 4284 heap()->ProcessWeakListRoots(&evacuation_object_retainer); | 4390 heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
| 4285 } | 4391 } |
| 4286 } | 4392 } |
| 4287 | 4393 |
| 4288 void MinorMarkCompactCollector::UpdatePointersAfterEvacuation() { | 4394 void MinorMarkCompactCollector::UpdatePointersAfterEvacuation() { |
| 4289 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | 4395 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
| 4290 | 4396 |
| 4291 PointersUpdatingVisitor updating_visitor; | 4397 PointersUpdatingVisitor updating_visitor; |
| 4292 | 4398 |
| 4293 { | 4399 { |
| 4294 TRACE_GC(heap()->tracer(), | 4400 TRACE_GC(heap()->tracer(), |
| 4295 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 4401 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 4296 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_, | 4402 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_, |
| 4297 *this); | 4403 *this); |
| 4298 // TODO(mlippautz): Iteration mode is not optimal as we process all | 4404 // TODO(mlippautz): Iteration mode is not optimal as we process all |
| 4299 // global handles. Find a way to only process the ones related to new | 4405 // global handles. Find a way to only process the ones related to new |
| 4300 // space. | 4406 // space. |
| 4301 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 4407 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 4302 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); | 4408 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_, |
| 4409 this); |
| 4303 } | 4410 } |
| 4304 | 4411 |
| 4305 { | 4412 { |
| 4306 TRACE_GC(heap()->tracer(), | 4413 TRACE_GC(heap()->tracer(), |
| 4307 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); | 4414 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
| 4308 | 4415 |
| 4309 EvacuationWeakObjectRetainer evacuation_object_retainer; | 4416 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 4310 heap()->ProcessWeakListRoots(&evacuation_object_retainer); | 4417 heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
| 4311 | 4418 |
| 4312 // Update pointers from external string table. | 4419 // Update pointers from external string table. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4350 int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page, | 4457 int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page, |
| 4351 AllocationSpace identity) { | 4458 AllocationSpace identity) { |
| 4352 int max_freed = 0; | 4459 int max_freed = 0; |
| 4353 { | 4460 { |
| 4354 base::LockGuard<base::RecursiveMutex> guard(page->mutex()); | 4461 base::LockGuard<base::RecursiveMutex> guard(page->mutex()); |
| 4355 // If this page was already swept in the meantime, we can return here. | 4462 // If this page was already swept in the meantime, we can return here. |
| 4356 if (page->SweepingDone()) return 0; | 4463 if (page->SweepingDone()) return 0; |
| 4357 DCHECK_EQ(Page::kSweepingPending, | 4464 DCHECK_EQ(Page::kSweepingPending, |
| 4358 page->concurrent_sweeping_state().Value()); | 4465 page->concurrent_sweeping_state().Value()); |
| 4359 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 4466 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 4360 const Sweeper::FreeSpaceTreatmentMode free_space_mode = | 4467 const FreeSpaceTreatmentMode free_space_mode = |
| 4361 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; | 4468 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; |
| 4362 if (identity == NEW_SPACE) { | 4469 if (identity == NEW_SPACE) { |
| 4363 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); | 4470 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); |
| 4364 } else { | 4471 } else { |
| 4365 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); | 4472 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); |
| 4366 } | 4473 } |
| 4367 DCHECK(page->SweepingDone()); | 4474 DCHECK(page->SweepingDone()); |
| 4368 | 4475 |
| 4369 // After finishing sweeping of a page we clean up its remembered set. | 4476 // After finishing sweeping of a page we clean up its remembered set. |
| 4370 TypedSlotSet* typed_slot_set = page->typed_slot_set<OLD_TO_NEW>(); | 4477 TypedSlotSet* typed_slot_set = page->typed_slot_set<OLD_TO_NEW>(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4435 continue; | 4542 continue; |
| 4436 } | 4543 } |
| 4437 | 4544 |
| 4438 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 4545 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 4439 // We need to sweep the page to get it into an iterable state again. Note | 4546 // We need to sweep the page to get it into an iterable state again. Note |
| 4440 // that this adds unusable memory into the free list that is later on | 4547 // that this adds unusable memory into the free list that is later on |
| 4441 // (in the free list) dropped again. Since we only use the flag for | 4548 // (in the free list) dropped again. Since we only use the flag for |
| 4442 // testing this is fine. | 4549 // testing this is fine. |
| 4443 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 4550 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 4444 Sweeper::RawSweep(p, Sweeper::IGNORE_FREE_LIST, | 4551 Sweeper::RawSweep(p, Sweeper::IGNORE_FREE_LIST, |
| 4445 Heap::ShouldZapGarbage() ? Sweeper::ZAP_FREE_SPACE | 4552 Heap::ShouldZapGarbage() |
| 4446 : Sweeper::IGNORE_FREE_SPACE); | 4553 ? FreeSpaceTreatmentMode::ZAP_FREE_SPACE |
| 4554 : FreeSpaceTreatmentMode::IGNORE_FREE_SPACE); |
| 4447 continue; | 4555 continue; |
| 4448 } | 4556 } |
| 4449 | 4557 |
| 4450 // One unused page is kept, all further are released before sweeping them. | 4558 // One unused page is kept, all further are released before sweeping them. |
| 4451 if (MarkingState::Internal(p).live_bytes() == 0) { | 4559 if (MarkingState::Internal(p).live_bytes() == 0) { |
| 4452 if (unused_page_present) { | 4560 if (unused_page_present) { |
| 4453 if (FLAG_gc_verbose) { | 4561 if (FLAG_gc_verbose) { |
| 4454 PrintIsolate(isolate(), "sweeping: released page: %p", | 4562 PrintIsolate(isolate(), "sweeping: released page: %p", |
| 4455 static_cast<void*>(p)); | 4563 static_cast<void*>(p)); |
| 4456 } | 4564 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4530 // The target is always in old space, we don't have to record the slot in | 4638 // The target is always in old space, we don't have to record the slot in |
| 4531 // the old-to-new remembered set. | 4639 // the old-to-new remembered set. |
| 4532 DCHECK(!heap()->InNewSpace(target)); | 4640 DCHECK(!heap()->InNewSpace(target)); |
| 4533 RecordRelocSlot(host, &rinfo, target); | 4641 RecordRelocSlot(host, &rinfo, target); |
| 4534 } | 4642 } |
| 4535 } | 4643 } |
| 4536 } | 4644 } |
| 4537 | 4645 |
| 4538 } // namespace internal | 4646 } // namespace internal |
| 4539 } // namespace v8 | 4647 } // namespace v8 |
| OLD | NEW |