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 <deque> | 8 #include <deque> |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
11 #include "src/base/platform/condition-variable.h" | 11 #include "src/base/platform/condition-variable.h" |
12 #include "src/cancelable-task.h" | 12 #include "src/cancelable-task.h" |
13 #include "src/heap/marking.h" | 13 #include "src/heap/marking.h" |
14 #include "src/heap/spaces.h" | 14 #include "src/heap/spaces.h" |
15 #include "src/heap/store-buffer.h" | 15 #include "src/heap/store-buffer.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
20 // Callback function, returns whether an object is alive. The heap size | |
21 // of the object is returned in size. It optionally updates the offset | |
22 // to the first live object in the page (only used for old and map objects). | |
23 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); | |
24 | |
25 // Callback function to mark an object in a given heap. | |
26 typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object); | |
27 | |
28 // Forward declarations. | 20 // Forward declarations. |
29 class CodeFlusher; | 21 class CodeFlusher; |
30 class HeapObjectVisitor; | 22 class HeapObjectVisitor; |
31 class MarkCompactCollector; | 23 class MarkCompactCollector; |
32 class MinorMarkCompactCollector; | 24 class MinorMarkCompactCollector; |
33 class MarkingVisitor; | 25 class MarkingVisitor; |
| 26 class ThreadLocalTop; |
34 | 27 |
35 class ObjectMarking : public AllStatic { | 28 class ObjectMarking : public AllStatic { |
36 public: | 29 public: |
37 V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj, | 30 V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj, |
38 const MarkingState& state) { | 31 const MarkingState& state) { |
39 const Address address = obj->address(); | 32 const Address address = obj->address(); |
40 const MemoryChunk* p = MemoryChunk::FromAddress(address); | 33 const MemoryChunk* p = MemoryChunk::FromAddress(address); |
41 return state.bitmap()->MarkBitFromIndex(p->AddressToMarkbitIndex(address)); | 34 return state.bitmap()->MarkBitFromIndex(p->AddressToMarkbitIndex(address)); |
42 } | 35 } |
43 | 36 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 SharedFunctionInfo* next_candidate); | 296 SharedFunctionInfo* next_candidate); |
304 static inline void ClearNextCandidate(SharedFunctionInfo* candidate); | 297 static inline void ClearNextCandidate(SharedFunctionInfo* candidate); |
305 | 298 |
306 Isolate* isolate_; | 299 Isolate* isolate_; |
307 JSFunction* jsfunction_candidates_head_; | 300 JSFunction* jsfunction_candidates_head_; |
308 SharedFunctionInfo* shared_function_info_candidates_head_; | 301 SharedFunctionInfo* shared_function_info_candidates_head_; |
309 | 302 |
310 DISALLOW_COPY_AND_ASSIGN(CodeFlusher); | 303 DISALLOW_COPY_AND_ASSIGN(CodeFlusher); |
311 }; | 304 }; |
312 | 305 |
313 | |
314 // Defined in isolate.h. | |
315 class ThreadLocalTop; | |
316 | |
317 class MarkBitCellIterator BASE_EMBEDDED { | 306 class MarkBitCellIterator BASE_EMBEDDED { |
318 public: | 307 public: |
319 MarkBitCellIterator(MemoryChunk* chunk, MarkingState state) : chunk_(chunk) { | 308 MarkBitCellIterator(MemoryChunk* chunk, MarkingState state) : chunk_(chunk) { |
320 last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex( | 309 last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex( |
321 chunk_->AddressToMarkbitIndex(chunk_->area_end()))); | 310 chunk_->AddressToMarkbitIndex(chunk_->area_end()))); |
322 cell_base_ = chunk_->area_start(); | 311 cell_base_ = chunk_->area_start(); |
323 cell_index_ = Bitmap::IndexToCell( | 312 cell_index_ = Bitmap::IndexToCell( |
324 Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_))); | 313 Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_))); |
325 cells_ = state.bitmap()->cells(); | 314 cells_ = state.bitmap()->cells(); |
326 } | 315 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 template <class Visitor> | 404 template <class Visitor> |
416 bool VisitBlackObjects(MemoryChunk* chunk, const MarkingState& state, | 405 bool VisitBlackObjects(MemoryChunk* chunk, const MarkingState& state, |
417 Visitor* visitor, IterationMode iteration_mode); | 406 Visitor* visitor, IterationMode iteration_mode); |
418 | 407 |
419 private: | 408 private: |
420 void RecomputeLiveBytes(MemoryChunk* chunk, const MarkingState& state); | 409 void RecomputeLiveBytes(MemoryChunk* chunk, const MarkingState& state); |
421 }; | 410 }; |
422 | 411 |
423 enum PageEvacuationMode { NEW_TO_NEW, NEW_TO_OLD }; | 412 enum PageEvacuationMode { NEW_TO_NEW, NEW_TO_OLD }; |
424 | 413 |
425 class MinorMarkCompactCollector { | 414 // Base class for minor and full MC collectors. |
| 415 class MarkCompactCollectorBase { |
| 416 public: |
| 417 virtual ~MarkCompactCollectorBase() {} |
| 418 virtual void SetUp() = 0; |
| 419 virtual void TearDown() = 0; |
| 420 virtual void CollectGarbage() = 0; |
| 421 |
| 422 inline Heap* heap() const { return heap_; } |
| 423 inline Isolate* isolate() { return heap()->isolate(); } |
| 424 |
| 425 protected: |
| 426 explicit MarkCompactCollectorBase(Heap* heap) : heap_(heap) {} |
| 427 |
| 428 virtual void MarkLiveObjects() = 0; |
| 429 |
| 430 // The number of parallel compaction tasks, including the main thread. |
| 431 int NumberOfParallelCompactionTasks(int pages, intptr_t live_bytes); |
| 432 |
| 433 Heap* heap_; |
| 434 }; |
| 435 |
| 436 // Collector for young-generation only. |
| 437 class MinorMarkCompactCollector final : public MarkCompactCollectorBase { |
426 public: | 438 public: |
427 explicit MinorMarkCompactCollector(Heap* heap) | 439 explicit MinorMarkCompactCollector(Heap* heap) |
428 : heap_(heap), marking_deque_(heap) {} | 440 : MarkCompactCollectorBase(heap), marking_deque_(heap) {} |
429 | 441 |
430 void SetUp(); | 442 void SetUp() override; |
431 void TearDown(); | 443 void TearDown() override; |
432 | 444 void CollectGarbage() override; |
433 void CollectGarbage(); | |
434 | |
435 inline Heap* heap() const { return heap_; } | |
436 | 445 |
437 private: | 446 private: |
438 class RootMarkingVisitor; | 447 class RootMarkingVisitor; |
439 | 448 |
440 inline Isolate* isolate() { return heap()->isolate(); } | |
441 inline MarkingDeque* marking_deque() { return &marking_deque_; } | 449 inline MarkingDeque* marking_deque() { return &marking_deque_; } |
442 | 450 |
443 V8_INLINE void MarkObject(HeapObject* obj); | 451 V8_INLINE void MarkObject(HeapObject* obj); |
444 V8_INLINE void PushBlack(HeapObject* obj); | 452 V8_INLINE void PushBlack(HeapObject* obj); |
445 | 453 |
446 SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address); | 454 SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address); |
447 void MarkLiveObjects(); | 455 void MarkLiveObjects() override; |
448 void ProcessMarkingDeque(); | 456 void ProcessMarkingDeque(); |
449 void EmptyMarkingDeque(); | 457 void EmptyMarkingDeque(); |
450 | 458 |
451 Heap* heap_; | |
452 MarkingDeque marking_deque_; | 459 MarkingDeque marking_deque_; |
453 | 460 |
454 friend class StaticYoungGenerationMarkingVisitor; | 461 friend class StaticYoungGenerationMarkingVisitor; |
455 }; | 462 }; |
456 | 463 |
457 // ------------------------------------------------------------------------- | 464 // Collector for young and old generation. |
458 // Mark-Compact collector | 465 class MarkCompactCollector final : public MarkCompactCollectorBase { |
459 class MarkCompactCollector { | |
460 public: | 466 public: |
461 class RootMarkingVisitor; | 467 class RootMarkingVisitor; |
462 | 468 |
463 class Sweeper { | 469 class Sweeper { |
464 public: | 470 public: |
465 class SweeperTask; | 471 class SweeperTask; |
466 | 472 |
467 enum FreeListRebuildingMode { REBUILD_FREE_LIST, IGNORE_FREE_LIST }; | 473 enum FreeListRebuildingMode { REBUILD_FREE_LIST, IGNORE_FREE_LIST }; |
468 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; | 474 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; |
469 enum ClearOldToNewSlotsMode { | 475 enum ClearOldToNewSlotsMode { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 base::AtomicNumber<intptr_t> num_sweeping_tasks_; | 542 base::AtomicNumber<intptr_t> num_sweeping_tasks_; |
537 }; | 543 }; |
538 | 544 |
539 enum IterationMode { | 545 enum IterationMode { |
540 kKeepMarking, | 546 kKeepMarking, |
541 kClearMarkbits, | 547 kClearMarkbits, |
542 }; | 548 }; |
543 | 549 |
544 static void Initialize(); | 550 static void Initialize(); |
545 | 551 |
546 static SlotCallbackResult CheckAndMarkObject(Heap* heap, | 552 void SetUp() override; |
547 Address slot_address); | 553 void TearDown() override; |
548 | 554 // Performs a global garbage collection. |
549 void SetUp(); | 555 void CollectGarbage() override; |
550 | |
551 void TearDown(); | |
552 | 556 |
553 void CollectEvacuationCandidates(PagedSpace* space); | 557 void CollectEvacuationCandidates(PagedSpace* space); |
554 | 558 |
555 void AddEvacuationCandidate(Page* p); | 559 void AddEvacuationCandidate(Page* p); |
556 | 560 |
557 // Prepares for GC by resetting relocation info in old and map spaces and | 561 // Prepares for GC by resetting relocation info in old and map spaces and |
558 // choosing spaces to compact. | 562 // choosing spaces to compact. |
559 void Prepare(); | 563 void Prepare(); |
560 | 564 |
561 // Performs a global garbage collection. | |
562 void CollectGarbage(); | |
563 | |
564 bool StartCompaction(); | 565 bool StartCompaction(); |
565 | 566 |
566 void AbortCompaction(); | 567 void AbortCompaction(); |
567 | 568 |
568 // Determine type of object and emit deletion log event. | 569 // Determine type of object and emit deletion log event. |
569 static void ReportDeleteIfNeeded(HeapObject* obj, Isolate* isolate); | 570 static void ReportDeleteIfNeeded(HeapObject* obj, Isolate* isolate); |
570 | 571 |
571 // Distinguishable invalid map encodings (for single word and multiple words) | 572 // Distinguishable invalid map encodings (for single word and multiple words) |
572 // that indicate free regions. | 573 // that indicate free regions. |
573 static const uint32_t kSingleFreeEncoding = 0; | 574 static const uint32_t kSingleFreeEncoding = 0; |
574 static const uint32_t kMultiFreeEncoding = 1; | 575 static const uint32_t kMultiFreeEncoding = 1; |
575 | 576 |
576 inline Heap* heap() const { return heap_; } | |
577 inline Isolate* isolate() const; | 577 inline Isolate* isolate() const; |
578 | 578 |
579 CodeFlusher* code_flusher() { return code_flusher_; } | 579 CodeFlusher* code_flusher() { return code_flusher_; } |
580 inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; } | 580 inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; } |
581 | 581 |
582 INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) { | 582 INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) { |
583 return Page::FromAddress(reinterpret_cast<Address>(host)) | 583 return Page::FromAddress(reinterpret_cast<Address>(host)) |
584 ->ShouldSkipEvacuationSlotRecording(); | 584 ->ShouldSkipEvacuationSlotRecording(); |
585 } | 585 } |
586 | 586 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 int* target_fragmentation_percent, | 652 int* target_fragmentation_percent, |
653 size_t* max_evacuated_bytes); | 653 size_t* max_evacuated_bytes); |
654 | 654 |
655 void VisitAllObjects(HeapObjectVisitor* visitor); | 655 void VisitAllObjects(HeapObjectVisitor* visitor); |
656 | 656 |
657 void RecordObjectStats(); | 657 void RecordObjectStats(); |
658 | 658 |
659 // Finishes GC, performs heap verification if enabled. | 659 // Finishes GC, performs heap verification if enabled. |
660 void Finish(); | 660 void Finish(); |
661 | 661 |
662 // ----------------------------------------------------------------------- | |
663 // Phase 1: Marking live objects. | |
664 // | |
665 // Before: The heap has been prepared for garbage collection by | |
666 // MarkCompactCollector::Prepare() and is otherwise in its | |
667 // normal state. | |
668 // | |
669 // After: Live objects are marked and non-live objects are unmarked. | |
670 | |
671 friend class CodeMarkingVisitor; | |
672 friend class IncrementalMarkingMarkingVisitor; | |
673 friend class MarkCompactMarkingVisitor; | |
674 friend class MarkingVisitor; | |
675 friend class RecordMigratedSlotVisitor; | |
676 friend class SharedFunctionInfoMarkingVisitor; | |
677 friend class StaticYoungGenerationMarkingVisitor; | |
678 | |
679 // Mark code objects that are active on the stack to prevent them | 662 // Mark code objects that are active on the stack to prevent them |
680 // from being flushed. | 663 // from being flushed. |
681 void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top); | 664 void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top); |
682 | 665 |
683 void PrepareForCodeFlushing(); | 666 void PrepareForCodeFlushing(); |
684 | 667 |
685 // Marking operations for objects reachable from roots. | 668 // Marking operations for objects reachable from roots. |
686 void MarkLiveObjects(); | 669 void MarkLiveObjects() override; |
687 | 670 |
688 // Pushes a black object onto the marking stack and accounts for live bytes. | 671 // Pushes a black object onto the marking stack and accounts for live bytes. |
689 // Note that this assumes live bytes have not yet been counted. | 672 // Note that this assumes live bytes have not yet been counted. |
690 V8_INLINE void PushBlack(HeapObject* obj); | 673 V8_INLINE void PushBlack(HeapObject* obj); |
691 | 674 |
692 // Unshifts a black object into the marking stack and accounts for live bytes. | 675 // Unshifts a black object into the marking stack and accounts for live bytes. |
693 // Note that this assumes lives bytes have already been counted. | 676 // Note that this assumes lives bytes have already been counted. |
694 V8_INLINE void UnshiftBlack(HeapObject* obj); | 677 V8_INLINE void UnshiftBlack(HeapObject* obj); |
695 | 678 |
696 // Marks the object black and pushes it on the marking stack. | 679 // Marks the object black and pushes it on the marking stack. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 | 769 |
787 // Starts sweeping of spaces by contributing on the main thread and setting | 770 // Starts sweeping of spaces by contributing on the main thread and setting |
788 // up other pages for sweeping. Does not start sweeper tasks. | 771 // up other pages for sweeping. Does not start sweeper tasks. |
789 void StartSweepSpaces(); | 772 void StartSweepSpaces(); |
790 void StartSweepSpace(PagedSpace* space); | 773 void StartSweepSpace(PagedSpace* space); |
791 | 774 |
792 void EvacuatePrologue(); | 775 void EvacuatePrologue(); |
793 void EvacuateEpilogue(); | 776 void EvacuateEpilogue(); |
794 void EvacuatePagesInParallel(); | 777 void EvacuatePagesInParallel(); |
795 | 778 |
796 // The number of parallel compaction tasks, including the main thread. | |
797 int NumberOfParallelCompactionTasks(int pages, intptr_t live_bytes); | |
798 | |
799 void EvacuateNewSpaceAndCandidates(); | 779 void EvacuateNewSpaceAndCandidates(); |
800 | 780 |
801 void UpdatePointersAfterEvacuation(); | 781 void UpdatePointersAfterEvacuation(); |
802 | 782 |
803 void ReleaseEvacuationCandidates(); | 783 void ReleaseEvacuationCandidates(); |
804 | 784 |
805 | |
806 #ifdef DEBUG | |
807 friend class MarkObjectVisitor; | |
808 static void VisitObject(HeapObject* obj); | |
809 | |
810 friend class UnmarkObjectVisitor; | |
811 static void UnmarkObject(HeapObject* obj); | |
812 #endif | |
813 | |
814 Heap* heap_; | |
815 | |
816 base::Semaphore page_parallel_job_semaphore_; | 785 base::Semaphore page_parallel_job_semaphore_; |
817 | 786 |
818 #ifdef DEBUG | 787 #ifdef DEBUG |
819 enum CollectorState { | 788 enum CollectorState { |
820 IDLE, | 789 IDLE, |
821 PREPARE_GC, | 790 PREPARE_GC, |
822 MARK_LIVE_OBJECTS, | 791 MARK_LIVE_OBJECTS, |
823 SWEEP_SPACES, | 792 SWEEP_SPACES, |
824 ENCODE_FORWARDING_ADDRESSES, | 793 ENCODE_FORWARDING_ADDRESSES, |
825 UPDATE_POINTERS, | 794 UPDATE_POINTERS, |
(...skipping 21 matching lines...) Expand all Loading... |
847 CodeFlusher* code_flusher_; | 816 CodeFlusher* code_flusher_; |
848 | 817 |
849 // Candidates for pages that should be evacuated. | 818 // Candidates for pages that should be evacuated. |
850 List<Page*> evacuation_candidates_; | 819 List<Page*> evacuation_candidates_; |
851 // Pages that are actually processed during evacuation. | 820 // Pages that are actually processed during evacuation. |
852 List<Page*> old_space_evacuation_pages_; | 821 List<Page*> old_space_evacuation_pages_; |
853 List<Page*> new_space_evacuation_pages_; | 822 List<Page*> new_space_evacuation_pages_; |
854 | 823 |
855 Sweeper sweeper_; | 824 Sweeper sweeper_; |
856 | 825 |
| 826 friend class CodeMarkingVisitor; |
857 friend class Heap; | 827 friend class Heap; |
| 828 friend class IncrementalMarkingMarkingVisitor; |
| 829 friend class MarkCompactMarkingVisitor; |
| 830 friend class MarkingVisitor; |
| 831 friend class RecordMigratedSlotVisitor; |
| 832 friend class SharedFunctionInfoMarkingVisitor; |
| 833 friend class StaticYoungGenerationMarkingVisitor; |
858 friend class StoreBuffer; | 834 friend class StoreBuffer; |
859 }; | 835 }; |
860 | 836 |
861 | |
862 class EvacuationScope BASE_EMBEDDED { | 837 class EvacuationScope BASE_EMBEDDED { |
863 public: | 838 public: |
864 explicit EvacuationScope(MarkCompactCollector* collector) | 839 explicit EvacuationScope(MarkCompactCollector* collector) |
865 : collector_(collector) { | 840 : collector_(collector) { |
866 collector_->set_evacuation(true); | 841 collector_->set_evacuation(true); |
867 } | 842 } |
868 | 843 |
869 ~EvacuationScope() { collector_->set_evacuation(false); } | 844 ~EvacuationScope() { collector_->set_evacuation(false); } |
870 | 845 |
871 private: | 846 private: |
872 MarkCompactCollector* collector_; | 847 MarkCompactCollector* collector_; |
873 }; | 848 }; |
874 | 849 |
875 V8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space); | |
876 } // namespace internal | 850 } // namespace internal |
877 } // namespace v8 | 851 } // namespace v8 |
878 | 852 |
879 #endif // V8_HEAP_MARK_COMPACT_H_ | 853 #endif // V8_HEAP_MARK_COMPACT_H_ |
OLD | NEW |