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