| 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 #ifndef V8_HEAP_MARK_COMPACT_H_ | 5 #ifndef V8_HEAP_MARK_COMPACT_H_ |
| 6 #define V8_HEAP_MARK_COMPACT_H_ | 6 #define V8_HEAP_MARK_COMPACT_H_ |
| 7 | 7 |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/heap/spaces.h" | 9 #include "src/heap/spaces.h" |
| 10 #include "src/heap/store-buffer.h" | 10 #include "src/heap/store-buffer.h" |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 Address cell_base_; | 393 Address cell_base_; |
| 394 MarkBit::CellType current_cell_; | 394 MarkBit::CellType current_cell_; |
| 395 }; | 395 }; |
| 396 | 396 |
| 397 // ------------------------------------------------------------------------- | 397 // ------------------------------------------------------------------------- |
| 398 // Mark-Compact collector | 398 // Mark-Compact collector |
| 399 class MarkCompactCollector { | 399 class MarkCompactCollector { |
| 400 public: | 400 public: |
| 401 class Evacuator; | 401 class Evacuator; |
| 402 | 402 |
| 403 class Sweeper { |
| 404 public: |
| 405 class SweeperTask; |
| 406 |
| 407 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; |
| 408 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; |
| 409 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; |
| 410 enum SweepingParallelism { SWEEP_ON_MAIN_THREAD, SWEEP_IN_PARALLEL }; |
| 411 |
| 412 typedef std::vector<Page*> SweepingList; |
| 413 typedef List<Page*> SweptList; |
| 414 |
| 415 enum SweepingSpace { |
| 416 kOldSpace, |
| 417 kCodeSpace, |
| 418 kMapSpace, |
| 419 kNumberOfSweepingSpaces, |
| 420 }; |
| 421 |
| 422 template <SweepingMode sweeping_mode, SweepingParallelism parallelism, |
| 423 SkipListRebuildingMode skip_list_mode, |
| 424 FreeSpaceTreatmentMode free_space_mode> |
| 425 static int UnmanagedSweep(PagedSpace* space, Page* p, ObjectVisitor* v); |
| 426 |
| 427 explicit Sweeper(Heap* heap) |
| 428 : heap_(heap), |
| 429 pending_sweeper_tasks_semaphore_(0), |
| 430 sweeping_in_progress_(false) {} |
| 431 |
| 432 bool sweeping_in_progress() { return sweeping_in_progress_; } |
| 433 |
| 434 void AddPage(PagedSpace* space, Page* page); |
| 435 void AddLatePage(SweepingSpace space, Page* page); |
| 436 void CommitLateList(SweepingSpace space); |
| 437 |
| 438 int HelpSweepInParallel(Page* page, PagedSpace* space); |
| 439 int HelpSweepInParallel(PagedSpace* space, int required_freed_bytes, |
| 440 int max_pages = 0); |
| 441 |
| 442 void StartSweeping(); |
| 443 void SweepOrWaitUntilSweepingCompleted(Page* page); |
| 444 void EnsureCompleted(); |
| 445 bool IsSweepingCompleted(); |
| 446 void ParallelSweepSpacesComplete(); |
| 447 |
| 448 void AddSweptPageSafe(PagedSpace* space, Page* page); |
| 449 Page* GetSweptPage(PagedSpace* space); |
| 450 |
| 451 private: |
| 452 AllocationSpace allocation_space(SweepingSpace space) { |
| 453 switch (space) { |
| 454 case kOldSpace: |
| 455 return OLD_SPACE; |
| 456 case kCodeSpace: |
| 457 return CODE_SPACE; |
| 458 case kMapSpace: |
| 459 return MAP_SPACE; |
| 460 default: |
| 461 UNREACHABLE(); |
| 462 } |
| 463 UNREACHABLE(); |
| 464 return OLD_SPACE; |
| 465 } |
| 466 |
| 467 SweepingSpace sweeping_space(AllocationSpace space) { |
| 468 switch (space) { |
| 469 case OLD_SPACE: |
| 470 return kOldSpace; |
| 471 case CODE_SPACE: |
| 472 return kCodeSpace; |
| 473 case MAP_SPACE: |
| 474 return kMapSpace; |
| 475 default: |
| 476 UNREACHABLE(); |
| 477 } |
| 478 UNREACHABLE(); |
| 479 return kOldSpace; |
| 480 } |
| 481 |
| 482 void PrepareAddPage(SweepingSpace space, Page* page); |
| 483 |
| 484 Heap* heap_; |
| 485 base::Mutex mutex_; |
| 486 base::Semaphore pending_sweeper_tasks_semaphore_; |
| 487 SweptList swept_list_[kNumberOfSweepingSpaces]; |
| 488 SweepingList sweeping_list_[kNumberOfSweepingSpaces]; |
| 489 SweepingList* late_sweeping_list_[kNumberOfSweepingSpaces]; |
| 490 SweepingList* tmp_late_sweeping_list_[kNumberOfSweepingSpaces]; |
| 491 bool sweeping_in_progress_; |
| 492 |
| 493 friend class SweeperTask; |
| 494 }; |
| 495 |
| 403 enum IterationMode { | 496 enum IterationMode { |
| 404 kKeepMarking, | 497 kKeepMarking, |
| 405 kClearMarkbits, | 498 kClearMarkbits, |
| 406 }; | 499 }; |
| 407 | 500 |
| 408 static void Initialize(); | 501 static void Initialize(); |
| 409 | 502 |
| 410 void SetUp(); | 503 void SetUp(); |
| 411 | 504 |
| 412 void TearDown(); | 505 void TearDown(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 void UpdateSlotsRecordedIn(SlotsBuffer* buffer); | 576 void UpdateSlotsRecordedIn(SlotsBuffer* buffer); |
| 484 | 577 |
| 485 void InvalidateCode(Code* code); | 578 void InvalidateCode(Code* code); |
| 486 | 579 |
| 487 void ClearMarkbits(); | 580 void ClearMarkbits(); |
| 488 | 581 |
| 489 bool is_compacting() const { return compacting_; } | 582 bool is_compacting() const { return compacting_; } |
| 490 | 583 |
| 491 MarkingParity marking_parity() { return marking_parity_; } | 584 MarkingParity marking_parity() { return marking_parity_; } |
| 492 | 585 |
| 493 // Concurrent and parallel sweeping support. If required_freed_bytes was set | |
| 494 // to a value larger than 0, then sweeping returns after a block of at least | |
| 495 // required_freed_bytes was freed. If required_freed_bytes was set to zero | |
| 496 // then the whole given space is swept. It returns the size of the maximum | |
| 497 // continuous freed memory chunk. | |
| 498 int SweepInParallel(PagedSpace* space, int required_freed_bytes, | |
| 499 int max_pages = 0); | |
| 500 | |
| 501 // Sweeps a given page concurrently to the sweeper threads. It returns the | |
| 502 // size of the maximum continuous freed memory chunk. | |
| 503 int SweepInParallel(Page* page, PagedSpace* space); | |
| 504 | |
| 505 // Ensures that sweeping is finished. | 586 // Ensures that sweeping is finished. |
| 506 // | 587 // |
| 507 // Note: Can only be called safely from main thread. | 588 // Note: Can only be called safely from main thread. |
| 508 void EnsureSweepingCompleted(); | 589 void EnsureSweepingCompleted(); |
| 509 | 590 |
| 510 void SweepOrWaitUntilSweepingCompleted(Page* page); | |
| 511 | |
| 512 // Help out in sweeping the corresponding space and refill memory that has | 591 // Help out in sweeping the corresponding space and refill memory that has |
| 513 // been regained. | 592 // been regained. |
| 514 // | 593 // |
| 515 // Note: Thread-safe. | 594 // Note: Thread-safe. |
| 516 void SweepAndRefill(CompactionSpace* space); | 595 void SweepAndRefill(CompactionSpace* space); |
| 517 | 596 |
| 518 // If sweeper threads are not active this method will return true. If | |
| 519 // this is a latency issue we should be smarter here. Otherwise, it will | |
| 520 // return true if the sweeper threads are done processing the pages. | |
| 521 bool IsSweepingCompleted(); | |
| 522 | |
| 523 // Checks if sweeping is in progress right now on any space. | 597 // Checks if sweeping is in progress right now on any space. |
| 524 bool sweeping_in_progress() { return sweeping_in_progress_; } | 598 bool sweeping_in_progress() { return sweeper().sweeping_in_progress(); } |
| 525 | 599 |
| 526 void set_evacuation(bool evacuation) { evacuation_ = evacuation; } | 600 void set_evacuation(bool evacuation) { evacuation_ = evacuation; } |
| 527 | 601 |
| 528 bool evacuation() const { return evacuation_; } | 602 bool evacuation() const { return evacuation_; } |
| 529 | 603 |
| 530 // Special case for processing weak references in a full collection. We need | 604 // Special case for processing weak references in a full collection. We need |
| 531 // to artificially keep AllocationSites alive for a time. | 605 // to artificially keep AllocationSites alive for a time. |
| 532 void MarkAllocationSite(AllocationSite* site); | 606 void MarkAllocationSite(AllocationSite* site); |
| 533 | 607 |
| 534 // Mark objects in implicit references groups if their parent object | 608 // Mark objects in implicit references groups if their parent object |
| (...skipping 20 matching lines...) Expand all Loading... |
| 555 // The following two methods can just be called after marking, when the | 629 // The following two methods can just be called after marking, when the |
| 556 // whole transitive closure is known. They must be called before sweeping | 630 // whole transitive closure is known. They must be called before sweeping |
| 557 // when mark bits are still intact. | 631 // when mark bits are still intact. |
| 558 bool IsSlotInBlackObject(MemoryChunk* p, Address slot); | 632 bool IsSlotInBlackObject(MemoryChunk* p, Address slot); |
| 559 HeapObject* FindBlackObjectBySlotSlow(Address slot); | 633 HeapObject* FindBlackObjectBySlotSlow(Address slot); |
| 560 | 634 |
| 561 // Removes all the slots in the slot buffers that are within the given | 635 // Removes all the slots in the slot buffers that are within the given |
| 562 // address range. | 636 // address range. |
| 563 void RemoveObjectSlots(Address start_slot, Address end_slot); | 637 void RemoveObjectSlots(Address start_slot, Address end_slot); |
| 564 | 638 |
| 565 base::Mutex* swept_pages_mutex() { return &swept_pages_mutex_; } | 639 Sweeper& sweeper() { return sweeper_; } |
| 566 List<Page*>* swept_pages(AllocationSpace id) { | |
| 567 switch (id) { | |
| 568 case OLD_SPACE: | |
| 569 return &swept_old_space_pages_; | |
| 570 case CODE_SPACE: | |
| 571 return &swept_code_space_pages_; | |
| 572 case MAP_SPACE: | |
| 573 return &swept_map_space_pages_; | |
| 574 default: | |
| 575 UNREACHABLE(); | |
| 576 } | |
| 577 return nullptr; | |
| 578 } | |
| 579 | 640 |
| 580 private: | 641 private: |
| 581 class EvacuateNewSpaceVisitor; | 642 class EvacuateNewSpaceVisitor; |
| 582 class EvacuateOldSpaceVisitor; | 643 class EvacuateOldSpaceVisitor; |
| 583 class EvacuateVisitorBase; | 644 class EvacuateVisitorBase; |
| 584 class HeapObjectVisitor; | 645 class HeapObjectVisitor; |
| 585 class SweeperTask; | |
| 586 | 646 |
| 587 typedef std::vector<Page*> SweepingList; | 647 typedef std::vector<Page*> SweepingList; |
| 588 | 648 |
| 589 explicit MarkCompactCollector(Heap* heap); | 649 explicit MarkCompactCollector(Heap* heap); |
| 590 | 650 |
| 591 bool WillBeDeoptimized(Code* code); | 651 bool WillBeDeoptimized(Code* code); |
| 592 void ClearInvalidRememberedSetSlots(); | 652 void ClearInvalidRememberedSetSlots(); |
| 593 | 653 |
| 594 void StartSweeperThreads(); | |
| 595 | |
| 596 void ComputeEvacuationHeuristics(int area_size, | 654 void ComputeEvacuationHeuristics(int area_size, |
| 597 int* target_fragmentation_percent, | 655 int* target_fragmentation_percent, |
| 598 int* max_evacuated_bytes); | 656 int* max_evacuated_bytes); |
| 599 | 657 |
| 600 #ifdef DEBUG | 658 #ifdef DEBUG |
| 601 enum CollectorState { | 659 enum CollectorState { |
| 602 IDLE, | 660 IDLE, |
| 603 PREPARE_GC, | 661 PREPARE_GC, |
| 604 MARK_LIVE_OBJECTS, | 662 MARK_LIVE_OBJECTS, |
| 605 SWEEP_SPACES, | 663 SWEEP_SPACES, |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 // Phase 2: Sweeping to clear mark bits and free non-live objects for | 812 // Phase 2: Sweeping to clear mark bits and free non-live objects for |
| 755 // a non-compacting collection. | 813 // a non-compacting collection. |
| 756 // | 814 // |
| 757 // Before: Live objects are marked and non-live objects are unmarked. | 815 // Before: Live objects are marked and non-live objects are unmarked. |
| 758 // | 816 // |
| 759 // After: Live objects are unmarked, non-live regions have been added to | 817 // After: Live objects are unmarked, non-live regions have been added to |
| 760 // their space's free list. Active eden semispace is compacted by | 818 // their space's free list. Active eden semispace is compacted by |
| 761 // evacuation. | 819 // evacuation. |
| 762 // | 820 // |
| 763 | 821 |
| 764 inline SweepingList& sweeping_list(Space* space); | |
| 765 | |
| 766 // If we are not compacting the heap, we simply sweep the spaces except | 822 // If we are not compacting the heap, we simply sweep the spaces except |
| 767 // for the large object space, clearing mark bits and adding unmarked | 823 // for the large object space, clearing mark bits and adding unmarked |
| 768 // regions to each space's free list. | 824 // regions to each space's free list. |
| 769 void SweepSpaces(); | 825 void SweepSpaces(); |
| 770 | 826 |
| 771 void EvacuateNewSpacePrologue(); | 827 void EvacuateNewSpacePrologue(); |
| 772 void EvacuateNewSpaceEpilogue(); | 828 void EvacuateNewSpaceEpilogue(); |
| 773 | 829 |
| 774 void EvacuatePagesInParallel(); | 830 void EvacuatePagesInParallel(); |
| 775 | 831 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 790 void RecomputeLiveBytes(MemoryChunk* page); | 846 void RecomputeLiveBytes(MemoryChunk* page); |
| 791 | 847 |
| 792 void SweepAbortedPages(); | 848 void SweepAbortedPages(); |
| 793 | 849 |
| 794 void ReleaseEvacuationCandidates(); | 850 void ReleaseEvacuationCandidates(); |
| 795 | 851 |
| 796 // Starts sweeping of a space by contributing on the main thread and setting | 852 // Starts sweeping of a space by contributing on the main thread and setting |
| 797 // up other pages for sweeping. | 853 // up other pages for sweeping. |
| 798 void StartSweepSpace(PagedSpace* space); | 854 void StartSweepSpace(PagedSpace* space); |
| 799 | 855 |
| 800 // Finalizes the parallel sweeping phase. Marks all the pages that were | |
| 801 // swept in parallel. | |
| 802 void ParallelSweepSpacesComplete(); | |
| 803 | |
| 804 #ifdef DEBUG | 856 #ifdef DEBUG |
| 805 friend class MarkObjectVisitor; | 857 friend class MarkObjectVisitor; |
| 806 static void VisitObject(HeapObject* obj); | 858 static void VisitObject(HeapObject* obj); |
| 807 | 859 |
| 808 friend class UnmarkObjectVisitor; | 860 friend class UnmarkObjectVisitor; |
| 809 static void UnmarkObject(HeapObject* obj); | 861 static void UnmarkObject(HeapObject* obj); |
| 810 #endif | 862 #endif |
| 811 | 863 |
| 812 Heap* heap_; | 864 Heap* heap_; |
| 813 base::VirtualMemory* marking_deque_memory_; | 865 base::VirtualMemory* marking_deque_memory_; |
| 814 size_t marking_deque_memory_committed_; | 866 size_t marking_deque_memory_committed_; |
| 815 MarkingDeque marking_deque_; | 867 MarkingDeque marking_deque_; |
| 816 CodeFlusher* code_flusher_; | 868 CodeFlusher* code_flusher_; |
| 817 bool have_code_to_deoptimize_; | 869 bool have_code_to_deoptimize_; |
| 818 | 870 |
| 819 List<Page*> evacuation_candidates_; | 871 List<Page*> evacuation_candidates_; |
| 820 List<NewSpacePage*> newspace_evacuation_candidates_; | 872 List<NewSpacePage*> newspace_evacuation_candidates_; |
| 821 | 873 |
| 822 base::Mutex swept_pages_mutex_; | |
| 823 List<Page*> swept_old_space_pages_; | |
| 824 List<Page*> swept_code_space_pages_; | |
| 825 List<Page*> swept_map_space_pages_; | |
| 826 | |
| 827 SweepingList sweeping_list_old_space_; | |
| 828 SweepingList sweeping_list_code_space_; | |
| 829 SweepingList sweeping_list_map_space_; | |
| 830 | |
| 831 // True if we are collecting slots to perform evacuation from evacuation | 874 // True if we are collecting slots to perform evacuation from evacuation |
| 832 // candidates. | 875 // candidates. |
| 833 bool compacting_; | 876 bool compacting_; |
| 834 | 877 |
| 835 // True if concurrent or parallel sweeping is currently in progress. | |
| 836 bool sweeping_in_progress_; | |
| 837 | |
| 838 // Semaphore used to synchronize sweeper tasks. | |
| 839 base::Semaphore pending_sweeper_tasks_semaphore_; | |
| 840 | |
| 841 // Semaphore used to synchronize compaction tasks. | 878 // Semaphore used to synchronize compaction tasks. |
| 842 base::Semaphore pending_compaction_tasks_semaphore_; | 879 base::Semaphore pending_compaction_tasks_semaphore_; |
| 843 | 880 |
| 844 bool black_allocation_; | 881 bool black_allocation_; |
| 845 | 882 |
| 883 Sweeper sweeper_; |
| 884 |
| 846 friend class Heap; | 885 friend class Heap; |
| 847 friend class StoreBuffer; | 886 friend class StoreBuffer; |
| 848 }; | 887 }; |
| 849 | 888 |
| 850 | 889 |
| 851 class EvacuationScope BASE_EMBEDDED { | 890 class EvacuationScope BASE_EMBEDDED { |
| 852 public: | 891 public: |
| 853 explicit EvacuationScope(MarkCompactCollector* collector) | 892 explicit EvacuationScope(MarkCompactCollector* collector) |
| 854 : collector_(collector) { | 893 : collector_(collector) { |
| 855 collector_->set_evacuation(true); | 894 collector_->set_evacuation(true); |
| 856 } | 895 } |
| 857 | 896 |
| 858 ~EvacuationScope() { collector_->set_evacuation(false); } | 897 ~EvacuationScope() { collector_->set_evacuation(false); } |
| 859 | 898 |
| 860 private: | 899 private: |
| 861 MarkCompactCollector* collector_; | 900 MarkCompactCollector* collector_; |
| 862 }; | 901 }; |
| 863 | 902 |
| 864 | 903 |
| 865 const char* AllocationSpaceName(AllocationSpace space); | 904 const char* AllocationSpaceName(AllocationSpace space); |
| 866 } // namespace internal | 905 } // namespace internal |
| 867 } // namespace v8 | 906 } // namespace v8 |
| 868 | 907 |
| 869 #endif // V8_HEAP_MARK_COMPACT_H_ | 908 #endif // V8_HEAP_MARK_COMPACT_H_ |
| OLD | NEW |