| 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" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 // Callback function, returns whether an object is alive. The heap size | 15 // Callback function, returns whether an object is alive. The heap size |
| 16 // of the object is returned in size. It optionally updates the offset | 16 // of the object is returned in size. It optionally updates the offset |
| 17 // to the first live object in the page (only used for old and map objects). | 17 // to the first live object in the page (only used for old and map objects). |
| 18 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); | 18 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); |
| 19 | 19 |
| 20 // Callback function to mark an object in a given heap. | 20 // Callback function to mark an object in a given heap. |
| 21 typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object); | 21 typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object); |
| 22 | 22 |
| 23 // Forward declarations. | 23 // Forward declarations. |
| 24 class CodeFlusher; | 24 class CodeFlusher; |
| 25 class MarkCompactCollector; | 25 class MarkCompactCollector; |
| 26 class MarkingVisitor; | 26 class MarkingVisitor; |
| 27 class RootMarkingVisitor; | 27 class RootMarkingVisitor; |
| 28 class SlotsBuffer; | 28 class LocalSlotsBuffer; |
| 29 class SlotsBufferAllocator; | |
| 30 | |
| 31 | 29 |
| 32 class Marking : public AllStatic { | 30 class Marking : public AllStatic { |
| 33 public: | 31 public: |
| 34 INLINE(static MarkBit MarkBitFrom(Address addr)) { | 32 INLINE(static MarkBit MarkBitFrom(Address addr)) { |
| 35 MemoryChunk* p = MemoryChunk::FromAddress(addr); | 33 MemoryChunk* p = MemoryChunk::FromAddress(addr); |
| 36 return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(addr)); | 34 return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(addr)); |
| 37 } | 35 } |
| 38 | 36 |
| 39 INLINE(static MarkBit MarkBitFrom(HeapObject* obj)) { | 37 INLINE(static MarkBit MarkBitFrom(HeapObject* obj)) { |
| 40 return MarkBitFrom(reinterpret_cast<Address>(obj)); | 38 return MarkBitFrom(reinterpret_cast<Address>(obj)); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) { | 386 INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) { |
| 389 return Page::FromAddress(reinterpret_cast<Address>(host)) | 387 return Page::FromAddress(reinterpret_cast<Address>(host)) |
| 390 ->ShouldSkipEvacuationSlotRecording(); | 388 ->ShouldSkipEvacuationSlotRecording(); |
| 391 } | 389 } |
| 392 | 390 |
| 393 INLINE(static bool IsOnEvacuationCandidate(Object* obj)) { | 391 INLINE(static bool IsOnEvacuationCandidate(Object* obj)) { |
| 394 return Page::FromAddress(reinterpret_cast<Address>(obj)) | 392 return Page::FromAddress(reinterpret_cast<Address>(obj)) |
| 395 ->IsEvacuationCandidate(); | 393 ->IsEvacuationCandidate(); |
| 396 } | 394 } |
| 397 | 395 |
| 398 void RecordRelocSlot(RelocInfo* rinfo, Object* target); | 396 void RecordRelocSlot(Code* host, RelocInfo* rinfo, Object* target); |
| 399 void RecordCodeEntrySlot(HeapObject* object, Address slot, Code* target); | 397 void RecordCodeEntrySlot(HeapObject* host, Address slot, Code* target); |
| 400 void RecordCodeTargetPatch(Address pc, Code* target); | 398 void RecordCodeTargetPatch(Address pc, Code* target); |
| 401 INLINE(void RecordSlot(HeapObject* object, Object** slot, Object* target)); | 399 INLINE(void RecordSlot(HeapObject* object, Object** slot, Object* target)); |
| 402 INLINE(void ForceRecordSlot(HeapObject* object, Object** slot, | 400 INLINE(void ForceRecordSlot(HeapObject* object, Object** slot, |
| 403 Object* target)); | 401 Object* target)); |
| 404 | 402 |
| 405 void UpdateSlots(SlotsBuffer* buffer); | 403 void UpdateSlots(SlotsBuffer* buffer); |
| 406 void UpdateSlotsRecordedIn(SlotsBuffer* buffer); | 404 void UpdateSlotsRecordedIn(SlotsBuffer* buffer); |
| 407 | 405 |
| 408 void MigrateObject(HeapObject* dst, HeapObject* src, int size, | 406 void MigrateObject(HeapObject* dst, HeapObject* src, int size, |
| 409 AllocationSpace to_old_space, | 407 AllocationSpace to_old_space, |
| 410 SlotsBuffer** evacuation_slots_buffer, | 408 LocalSlotsBuffer* old_to_old_slots, |
| 411 LocalStoreBuffer* local_store_buffer); | 409 LocalSlotsBuffer* old_to_new_slots); |
| 412 | 410 |
| 413 void InvalidateCode(Code* code); | 411 void InvalidateCode(Code* code); |
| 414 | 412 |
| 415 void ClearMarkbits(); | 413 void ClearMarkbits(); |
| 416 | 414 |
| 417 bool is_compacting() const { return compacting_; } | 415 bool is_compacting() const { return compacting_; } |
| 418 | 416 |
| 419 MarkingParity marking_parity() { return marking_parity_; } | 417 MarkingParity marking_parity() { return marking_parity_; } |
| 420 | 418 |
| 421 // Concurrent and parallel sweeping support. If required_freed_bytes was set | 419 // Concurrent and parallel sweeping support. If required_freed_bytes was set |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 | 475 |
| 478 void EnsureMarkingDequeIsCommitted(size_t max_size); | 476 void EnsureMarkingDequeIsCommitted(size_t max_size); |
| 479 void EnsureMarkingDequeIsReserved(); | 477 void EnsureMarkingDequeIsReserved(); |
| 480 | 478 |
| 481 void InitializeMarkingDeque(); | 479 void InitializeMarkingDeque(); |
| 482 | 480 |
| 483 // The following four methods can just be called after marking, when the | 481 // The following four methods can just be called after marking, when the |
| 484 // whole transitive closure is known. They must be called before sweeping | 482 // whole transitive closure is known. They must be called before sweeping |
| 485 // when mark bits are still intact. | 483 // when mark bits are still intact. |
| 486 bool IsSlotInBlackObject(Page* p, Address slot, HeapObject** out_object); | 484 bool IsSlotInBlackObject(Page* p, Address slot, HeapObject** out_object); |
| 487 bool IsSlotInBlackObjectSlow(Page* p, Address slot); | 485 HeapObject* FindBlackObjectBySlotSlow(Address slot); |
| 488 bool IsSlotInLiveObject(Address slot); | 486 bool IsSlotInLiveObject(Address slot); |
| 489 void VerifyIsSlotInLiveObject(Address slot, HeapObject* object); | |
| 490 | 487 |
| 491 // Removes all the slots in the slot buffers that are within the given | 488 // Removes all the slots in the slot buffers that are within the given |
| 492 // address range. | 489 // address range. |
| 493 void RemoveObjectSlots(Address start_slot, Address end_slot); | 490 void RemoveObjectSlots(Address start_slot, Address end_slot); |
| 494 | 491 |
| 495 // | 492 // |
| 496 // Free lists filled by sweeper and consumed by corresponding spaces | 493 // Free lists filled by sweeper and consumed by corresponding spaces |
| 497 // (including compaction spaces). | 494 // (including compaction spaces). |
| 498 // | 495 // |
| 499 base::SmartPointer<FreeList>& free_list_old_space() { | 496 base::SmartPointer<FreeList>& free_list_old_space() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 513 class EvacuateVisitorBase; | 510 class EvacuateVisitorBase; |
| 514 class Evacuator; | 511 class Evacuator; |
| 515 class HeapObjectVisitor; | 512 class HeapObjectVisitor; |
| 516 class SweeperTask; | 513 class SweeperTask; |
| 517 | 514 |
| 518 typedef std::vector<Page*> SweepingList; | 515 typedef std::vector<Page*> SweepingList; |
| 519 | 516 |
| 520 explicit MarkCompactCollector(Heap* heap); | 517 explicit MarkCompactCollector(Heap* heap); |
| 521 | 518 |
| 522 bool WillBeDeoptimized(Code* code); | 519 bool WillBeDeoptimized(Code* code); |
| 523 void EvictPopularEvacuationCandidate(Page* page); | 520 void ClearInvalidRememberedSetSlots(); |
| 524 void ClearInvalidStoreAndSlotsBufferEntries(); | |
| 525 | 521 |
| 526 void StartSweeperThreads(); | 522 void StartSweeperThreads(); |
| 527 | 523 |
| 528 void ComputeEvacuationHeuristics(int area_size, | 524 void ComputeEvacuationHeuristics(int area_size, |
| 529 int* target_fragmentation_percent, | 525 int* target_fragmentation_percent, |
| 530 int* max_evacuated_bytes); | 526 int* max_evacuated_bytes); |
| 531 | 527 |
| 532 #ifdef DEBUG | 528 #ifdef DEBUG |
| 533 enum CollectorState { | 529 enum CollectorState { |
| 534 IDLE, | 530 IDLE, |
| 535 PREPARE_GC, | 531 PREPARE_GC, |
| 536 MARK_LIVE_OBJECTS, | 532 MARK_LIVE_OBJECTS, |
| 537 SWEEP_SPACES, | 533 SWEEP_SPACES, |
| 538 ENCODE_FORWARDING_ADDRESSES, | 534 ENCODE_FORWARDING_ADDRESSES, |
| 539 UPDATE_POINTERS, | 535 UPDATE_POINTERS, |
| 540 RELOCATE_OBJECTS | 536 RELOCATE_OBJECTS |
| 541 }; | 537 }; |
| 542 | 538 |
| 543 // The current stage of the collector. | 539 // The current stage of the collector. |
| 544 CollectorState state_; | 540 CollectorState state_; |
| 545 #endif | 541 #endif |
| 546 | 542 |
| 547 MarkingParity marking_parity_; | 543 MarkingParity marking_parity_; |
| 548 | 544 |
| 549 bool was_marked_incrementally_; | 545 bool was_marked_incrementally_; |
| 550 | 546 |
| 551 bool evacuation_; | 547 bool evacuation_; |
| 552 | 548 |
| 553 SlotsBufferAllocator* slots_buffer_allocator_; | |
| 554 | |
| 555 SlotsBuffer* migration_slots_buffer_; | |
| 556 | |
| 557 // Finishes GC, performs heap verification if enabled. | 549 // Finishes GC, performs heap verification if enabled. |
| 558 void Finish(); | 550 void Finish(); |
| 559 | 551 |
| 560 // ----------------------------------------------------------------------- | 552 // ----------------------------------------------------------------------- |
| 561 // Phase 1: Marking live objects. | 553 // Phase 1: Marking live objects. |
| 562 // | 554 // |
| 563 // Before: The heap has been prepared for garbage collection by | 555 // Before: The heap has been prepared for garbage collection by |
| 564 // MarkCompactCollector::Prepare() and is otherwise in its | 556 // MarkCompactCollector::Prepare() and is otherwise in its |
| 565 // normal state. | 557 // normal state. |
| 566 // | 558 // |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 inline SweepingList& sweeping_list(Space* space); | 692 inline SweepingList& sweeping_list(Space* space); |
| 701 | 693 |
| 702 // If we are not compacting the heap, we simply sweep the spaces except | 694 // If we are not compacting the heap, we simply sweep the spaces except |
| 703 // for the large object space, clearing mark bits and adding unmarked | 695 // for the large object space, clearing mark bits and adding unmarked |
| 704 // regions to each space's free list. | 696 // regions to each space's free list. |
| 705 void SweepSpaces(); | 697 void SweepSpaces(); |
| 706 | 698 |
| 707 void EvacuateNewSpacePrologue(); | 699 void EvacuateNewSpacePrologue(); |
| 708 void EvacuateNewSpaceEpilogue(); | 700 void EvacuateNewSpaceEpilogue(); |
| 709 | 701 |
| 710 void AddEvacuationSlotsBufferSynchronized( | |
| 711 SlotsBuffer* evacuation_slots_buffer); | |
| 712 | |
| 713 void EvacuatePagesInParallel(); | 702 void EvacuatePagesInParallel(); |
| 714 | 703 |
| 715 // The number of parallel compaction tasks, including the main thread. | 704 // The number of parallel compaction tasks, including the main thread. |
| 716 int NumberOfParallelCompactionTasks(int pages, intptr_t live_bytes); | 705 int NumberOfParallelCompactionTasks(int pages, intptr_t live_bytes); |
| 717 | 706 |
| 718 void StartParallelCompaction(Evacuator** evacuators, int len); | 707 void StartParallelCompaction(Evacuator** evacuators, int len); |
| 719 void WaitUntilCompactionCompleted(Evacuator** evacuators, int len); | 708 void WaitUntilCompactionCompleted(Evacuator** evacuators, int len); |
| 720 | 709 |
| 721 void EvacuateNewSpaceAndCandidates(); | 710 void EvacuateNewSpaceAndCandidates(); |
| 722 | 711 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 738 // Starts sweeping of a space by contributing on the main thread and setting | 727 // Starts sweeping of a space by contributing on the main thread and setting |
| 739 // up other pages for sweeping. | 728 // up other pages for sweeping. |
| 740 void StartSweepSpace(PagedSpace* space); | 729 void StartSweepSpace(PagedSpace* space); |
| 741 | 730 |
| 742 // Finalizes the parallel sweeping phase. Marks all the pages that were | 731 // Finalizes the parallel sweeping phase. Marks all the pages that were |
| 743 // swept in parallel. | 732 // swept in parallel. |
| 744 void ParallelSweepSpacesComplete(); | 733 void ParallelSweepSpacesComplete(); |
| 745 | 734 |
| 746 // Updates store buffer and slot buffer for a pointer in a migrating object. | 735 // Updates store buffer and slot buffer for a pointer in a migrating object. |
| 747 void RecordMigratedSlot(Object* value, Address slot, | 736 void RecordMigratedSlot(Object* value, Address slot, |
| 748 SlotsBuffer** evacuation_slots_buffer, | 737 LocalSlotsBuffer* old_to_old_slots, |
| 749 LocalStoreBuffer* local_store_buffer); | 738 LocalSlotsBuffer* old_to_new_slots); |
| 750 | |
| 751 // Adds the code entry slot to the slots buffer. | |
| 752 void RecordMigratedCodeEntrySlot(Address code_entry, Address code_entry_slot, | |
| 753 SlotsBuffer** evacuation_slots_buffer); | |
| 754 | |
| 755 // Adds the slot of a moved code object. | |
| 756 void RecordMigratedCodeObjectSlot(Address code_object, | |
| 757 SlotsBuffer** evacuation_slots_buffer); | |
| 758 | 739 |
| 759 #ifdef DEBUG | 740 #ifdef DEBUG |
| 760 friend class MarkObjectVisitor; | 741 friend class MarkObjectVisitor; |
| 761 static void VisitObject(HeapObject* obj); | 742 static void VisitObject(HeapObject* obj); |
| 762 | 743 |
| 763 friend class UnmarkObjectVisitor; | 744 friend class UnmarkObjectVisitor; |
| 764 static void UnmarkObject(HeapObject* obj); | 745 static void UnmarkObject(HeapObject* obj); |
| 765 #endif | 746 #endif |
| 766 | 747 |
| 767 Heap* heap_; | 748 Heap* heap_; |
| 768 base::VirtualMemory* marking_deque_memory_; | 749 base::VirtualMemory* marking_deque_memory_; |
| 769 size_t marking_deque_memory_committed_; | 750 size_t marking_deque_memory_committed_; |
| 770 MarkingDeque marking_deque_; | 751 MarkingDeque marking_deque_; |
| 771 CodeFlusher* code_flusher_; | 752 CodeFlusher* code_flusher_; |
| 772 bool have_code_to_deoptimize_; | 753 bool have_code_to_deoptimize_; |
| 773 | 754 |
| 774 List<Page*> evacuation_candidates_; | 755 List<Page*> evacuation_candidates_; |
| 775 List<NewSpacePage*> newspace_evacuation_candidates_; | 756 List<NewSpacePage*> newspace_evacuation_candidates_; |
| 776 | 757 |
| 777 // The evacuation_slots_buffers_ are used by the compaction threads. | |
| 778 // When a compaction task finishes, it uses | |
| 779 // AddEvacuationSlotsbufferSynchronized to adds its slots buffer to the | |
| 780 // evacuation_slots_buffers_ list using the evacuation_slots_buffers_mutex_ | |
| 781 // lock. | |
| 782 base::Mutex evacuation_slots_buffers_mutex_; | |
| 783 List<SlotsBuffer*> evacuation_slots_buffers_; | |
| 784 | |
| 785 base::SmartPointer<FreeList> free_list_old_space_; | 758 base::SmartPointer<FreeList> free_list_old_space_; |
| 786 base::SmartPointer<FreeList> free_list_code_space_; | 759 base::SmartPointer<FreeList> free_list_code_space_; |
| 787 base::SmartPointer<FreeList> free_list_map_space_; | 760 base::SmartPointer<FreeList> free_list_map_space_; |
| 788 | 761 |
| 789 SweepingList sweeping_list_old_space_; | 762 SweepingList sweeping_list_old_space_; |
| 790 SweepingList sweeping_list_code_space_; | 763 SweepingList sweeping_list_code_space_; |
| 791 SweepingList sweeping_list_map_space_; | 764 SweepingList sweeping_list_map_space_; |
| 792 | 765 |
| 793 // True if we are collecting slots to perform evacuation from evacuation | 766 // True if we are collecting slots to perform evacuation from evacuation |
| 794 // candidates. | 767 // candidates. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 private: | 865 private: |
| 893 MarkCompactCollector* collector_; | 866 MarkCompactCollector* collector_; |
| 894 }; | 867 }; |
| 895 | 868 |
| 896 | 869 |
| 897 const char* AllocationSpaceName(AllocationSpace space); | 870 const char* AllocationSpaceName(AllocationSpace space); |
| 898 } // namespace internal | 871 } // namespace internal |
| 899 } // namespace v8 | 872 } // namespace v8 |
| 900 | 873 |
| 901 #endif // V8_HEAP_MARK_COMPACT_H_ | 874 #endif // V8_HEAP_MARK_COMPACT_H_ |
| OLD | NEW |