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