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