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 | 10 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 INLINE(static void BlackToGrey(HeapObject* obj)) { | 110 INLINE(static void BlackToGrey(HeapObject* obj)) { |
111 BlackToGrey(MarkBitFrom(obj)); | 111 BlackToGrey(MarkBitFrom(obj)); |
112 } | 112 } |
113 | 113 |
114 INLINE(static void AnyToGrey(MarkBit markbit)) { | 114 INLINE(static void AnyToGrey(MarkBit markbit)) { |
115 markbit.Set(); | 115 markbit.Set(); |
116 markbit.Next().Set(); | 116 markbit.Next().Set(); |
117 } | 117 } |
118 | 118 |
119 static void SetAllMarkBitsInRange(MarkBit start, MarkBit end); | |
120 static void ClearAllMarkBitsOfCellsContainedInRange(MarkBit start, | |
121 MarkBit end); | |
122 | |
123 void TransferMark(Address old_start, Address new_start); | 119 void TransferMark(Address old_start, Address new_start); |
124 | 120 |
125 #ifdef DEBUG | 121 #ifdef DEBUG |
126 enum ObjectColor { | 122 enum ObjectColor { |
127 BLACK_OBJECT, | 123 BLACK_OBJECT, |
128 WHITE_OBJECT, | 124 WHITE_OBJECT, |
129 GREY_OBJECT, | 125 GREY_OBJECT, |
130 IMPOSSIBLE_COLOR | 126 IMPOSSIBLE_COLOR |
131 }; | 127 }; |
132 | 128 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 void Add(ObjectSlot slot) { | 314 void Add(ObjectSlot slot) { |
319 DCHECK(0 <= idx_ && idx_ < kNumberOfElements); | 315 DCHECK(0 <= idx_ && idx_ < kNumberOfElements); |
320 #ifdef DEBUG | 316 #ifdef DEBUG |
321 if (slot >= reinterpret_cast<ObjectSlot>(NUMBER_OF_SLOT_TYPES)) { | 317 if (slot >= reinterpret_cast<ObjectSlot>(NUMBER_OF_SLOT_TYPES)) { |
322 DCHECK_NOT_NULL(*slot); | 318 DCHECK_NOT_NULL(*slot); |
323 } | 319 } |
324 #endif | 320 #endif |
325 slots_[idx_++] = slot; | 321 slots_[idx_++] = slot; |
326 } | 322 } |
327 | 323 |
| 324 // Should be used for testing only. |
| 325 ObjectSlot Get(intptr_t i) { |
| 326 DCHECK(i >= 0 && i < kNumberOfElements); |
| 327 return slots_[i]; |
| 328 } |
| 329 |
328 enum SlotType { | 330 enum SlotType { |
329 EMBEDDED_OBJECT_SLOT, | 331 EMBEDDED_OBJECT_SLOT, |
330 OBJECT_SLOT, | 332 OBJECT_SLOT, |
331 RELOCATED_CODE_OBJECT, | 333 RELOCATED_CODE_OBJECT, |
332 CELL_TARGET_SLOT, | 334 CELL_TARGET_SLOT, |
333 CODE_TARGET_SLOT, | 335 CODE_TARGET_SLOT, |
334 CODE_ENTRY_SLOT, | 336 CODE_ENTRY_SLOT, |
335 DEBUG_TARGET_SLOT, | 337 DEBUG_TARGET_SLOT, |
336 JS_RETURN_SLOT, | 338 JS_RETURN_SLOT, |
337 NUMBER_OF_SLOT_TYPES | 339 NUMBER_OF_SLOT_TYPES |
(...skipping 18 matching lines...) Expand all Loading... |
356 case JS_RETURN_SLOT: | 358 case JS_RETURN_SLOT: |
357 return "JS_RETURN_SLOT"; | 359 return "JS_RETURN_SLOT"; |
358 case NUMBER_OF_SLOT_TYPES: | 360 case NUMBER_OF_SLOT_TYPES: |
359 return "NUMBER_OF_SLOT_TYPES"; | 361 return "NUMBER_OF_SLOT_TYPES"; |
360 } | 362 } |
361 return "UNKNOWN SlotType"; | 363 return "UNKNOWN SlotType"; |
362 } | 364 } |
363 | 365 |
364 void UpdateSlots(Heap* heap); | 366 void UpdateSlots(Heap* heap); |
365 | 367 |
366 void UpdateSlotsWithFilter(Heap* heap); | |
367 | |
368 SlotsBuffer* next() { return next_; } | 368 SlotsBuffer* next() { return next_; } |
369 | 369 |
370 static int SizeOfChain(SlotsBuffer* buffer) { | 370 static int SizeOfChain(SlotsBuffer* buffer) { |
371 if (buffer == NULL) return 0; | 371 if (buffer == NULL) return 0; |
372 return static_cast<int>(buffer->idx_ + | 372 return static_cast<int>(buffer->idx_ + |
373 (buffer->chain_length_ - 1) * kNumberOfElements); | 373 (buffer->chain_length_ - 1) * kNumberOfElements); |
374 } | 374 } |
375 | 375 |
376 inline bool IsFull() { return idx_ == kNumberOfElements; } | 376 inline bool IsFull() { return idx_ == kNumberOfElements; } |
377 | 377 |
378 inline bool HasSpaceForTypedSlot() { return idx_ < kNumberOfElements - 1; } | 378 inline bool HasSpaceForTypedSlot() { return idx_ < kNumberOfElements - 1; } |
379 | 379 |
380 static void UpdateSlotsRecordedIn(Heap* heap, SlotsBuffer* buffer, | 380 static void UpdateSlotsRecordedIn(Heap* heap, SlotsBuffer* buffer) { |
381 bool code_slots_filtering_required) { | |
382 while (buffer != NULL) { | 381 while (buffer != NULL) { |
383 if (code_slots_filtering_required) { | 382 buffer->UpdateSlots(heap); |
384 buffer->UpdateSlotsWithFilter(heap); | |
385 } else { | |
386 buffer->UpdateSlots(heap); | |
387 } | |
388 buffer = buffer->next(); | 383 buffer = buffer->next(); |
389 } | 384 } |
390 } | 385 } |
391 | 386 |
392 enum AdditionMode { FAIL_ON_OVERFLOW, IGNORE_OVERFLOW }; | 387 enum AdditionMode { FAIL_ON_OVERFLOW, IGNORE_OVERFLOW }; |
393 | 388 |
394 static bool ChainLengthThresholdReached(SlotsBuffer* buffer) { | 389 static bool ChainLengthThresholdReached(SlotsBuffer* buffer) { |
395 return buffer != NULL && buffer->chain_length_ >= kChainLengthThreshold; | 390 return buffer != NULL && buffer->chain_length_ >= kChainLengthThreshold; |
396 } | 391 } |
397 | 392 |
(...skipping 18 matching lines...) Expand all Loading... |
416 static bool AddTo(SlotsBufferAllocator* allocator, | 411 static bool AddTo(SlotsBufferAllocator* allocator, |
417 SlotsBuffer** buffer_address, SlotType type, Address addr, | 412 SlotsBuffer** buffer_address, SlotType type, Address addr, |
418 AdditionMode mode); | 413 AdditionMode mode); |
419 | 414 |
420 // Eliminates all stale entries from the slots buffer, i.e., slots that | 415 // Eliminates all stale entries from the slots buffer, i.e., slots that |
421 // are not part of live objects anymore. This method must be called after | 416 // are not part of live objects anymore. This method must be called after |
422 // marking, when the whole transitive closure is known and must be called | 417 // marking, when the whole transitive closure is known and must be called |
423 // before sweeping when mark bits are still intact. | 418 // before sweeping when mark bits are still intact. |
424 static void RemoveInvalidSlots(Heap* heap, SlotsBuffer* buffer); | 419 static void RemoveInvalidSlots(Heap* heap, SlotsBuffer* buffer); |
425 | 420 |
| 421 // Eliminate all slots that point to the given invalid_object. |
| 422 static void RemoveObjectSlots(Heap* heap, SlotsBuffer* buffer, |
| 423 HeapObject* invalid_object); |
| 424 |
426 // Ensures that there are no invalid slots in the chain of slots buffers. | 425 // Ensures that there are no invalid slots in the chain of slots buffers. |
427 static void VerifySlots(Heap* heap, SlotsBuffer* buffer); | 426 static void VerifySlots(Heap* heap, SlotsBuffer* buffer); |
428 | 427 |
429 static const int kNumberOfElements = 1021; | 428 static const int kNumberOfElements = 1021; |
430 | 429 |
431 private: | 430 private: |
432 static const int kChainLengthThreshold = 15; | 431 static const int kChainLengthThreshold = 15; |
433 | 432 |
434 intptr_t idx_; | 433 intptr_t idx_; |
435 intptr_t chain_length_; | 434 intptr_t chain_length_; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 | 662 |
664 void MigrateObject(HeapObject* dst, HeapObject* src, int size, | 663 void MigrateObject(HeapObject* dst, HeapObject* src, int size, |
665 AllocationSpace to_old_space); | 664 AllocationSpace to_old_space); |
666 | 665 |
667 void MigrateObjectTagged(HeapObject* dst, HeapObject* src, int size); | 666 void MigrateObjectTagged(HeapObject* dst, HeapObject* src, int size); |
668 void MigrateObjectMixed(HeapObject* dst, HeapObject* src, int size); | 667 void MigrateObjectMixed(HeapObject* dst, HeapObject* src, int size); |
669 void MigrateObjectRaw(HeapObject* dst, HeapObject* src, int size); | 668 void MigrateObjectRaw(HeapObject* dst, HeapObject* src, int size); |
670 | 669 |
671 bool TryPromoteObject(HeapObject* object, int object_size); | 670 bool TryPromoteObject(HeapObject* object, int object_size); |
672 | 671 |
673 void InvalidateCode(Code* code); | |
674 | |
675 void ClearMarkbits(); | 672 void ClearMarkbits(); |
676 | 673 |
677 bool abort_incremental_marking() const { return abort_incremental_marking_; } | 674 bool abort_incremental_marking() const { return abort_incremental_marking_; } |
678 | 675 |
679 bool finalize_incremental_marking() const { | 676 bool finalize_incremental_marking() const { |
680 return finalize_incremental_marking_; | 677 return finalize_incremental_marking_; |
681 } | 678 } |
682 | 679 |
683 bool is_compacting() const { return compacting_; } | 680 bool is_compacting() const { return compacting_; } |
684 | 681 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 void InitializeMarkingDeque(); | 734 void InitializeMarkingDeque(); |
738 | 735 |
739 // The following four methods can just be called after marking, when the | 736 // The following four methods can just be called after marking, when the |
740 // whole transitive closure is known. They must be called before sweeping | 737 // whole transitive closure is known. They must be called before sweeping |
741 // when mark bits are still intact. | 738 // when mark bits are still intact. |
742 bool IsSlotInBlackObject(Page* p, Address slot, HeapObject** out_object); | 739 bool IsSlotInBlackObject(Page* p, Address slot, HeapObject** out_object); |
743 bool IsSlotInBlackObjectSlow(Page* p, Address slot); | 740 bool IsSlotInBlackObjectSlow(Page* p, Address slot); |
744 bool IsSlotInLiveObject(Address slot); | 741 bool IsSlotInLiveObject(Address slot); |
745 void VerifyIsSlotInLiveObject(Address slot, HeapObject* object); | 742 void VerifyIsSlotInLiveObject(Address slot, HeapObject* object); |
746 | 743 |
| 744 // Removes all the slots in the slot buffers that are within the given |
| 745 // invalid_object. |
| 746 void RemoveObjectSlots(HeapObject* invalid_object); |
| 747 |
747 private: | 748 private: |
748 class SweeperTask; | 749 class SweeperTask; |
749 | 750 |
750 explicit MarkCompactCollector(Heap* heap); | 751 explicit MarkCompactCollector(Heap* heap); |
751 ~MarkCompactCollector(); | 752 ~MarkCompactCollector(); |
752 | 753 |
753 bool MarkInvalidatedCode(); | |
754 bool WillBeDeoptimized(Code* code); | 754 bool WillBeDeoptimized(Code* code); |
755 void RemoveDeadInvalidatedCode(); | |
756 void ProcessInvalidatedCode(ObjectVisitor* visitor); | |
757 void EvictPopularEvacuationCandidate(Page* page); | 755 void EvictPopularEvacuationCandidate(Page* page); |
758 void ClearInvalidSlotsBufferEntries(PagedSpace* space); | 756 void ClearInvalidSlotsBufferEntries(PagedSpace* space); |
759 void ClearInvalidStoreAndSlotsBufferEntries(); | 757 void ClearInvalidStoreAndSlotsBufferEntries(); |
760 | 758 |
761 void StartSweeperThreads(); | 759 void StartSweeperThreads(); |
762 | 760 |
763 #ifdef DEBUG | 761 #ifdef DEBUG |
764 enum CollectorState { | 762 enum CollectorState { |
765 IDLE, | 763 IDLE, |
766 PREPARE_GC, | 764 PREPARE_GC, |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 #endif | 961 #endif |
964 | 962 |
965 Heap* heap_; | 963 Heap* heap_; |
966 base::VirtualMemory* marking_deque_memory_; | 964 base::VirtualMemory* marking_deque_memory_; |
967 size_t marking_deque_memory_committed_; | 965 size_t marking_deque_memory_committed_; |
968 MarkingDeque marking_deque_; | 966 MarkingDeque marking_deque_; |
969 CodeFlusher* code_flusher_; | 967 CodeFlusher* code_flusher_; |
970 bool have_code_to_deoptimize_; | 968 bool have_code_to_deoptimize_; |
971 | 969 |
972 List<Page*> evacuation_candidates_; | 970 List<Page*> evacuation_candidates_; |
973 List<Code*> invalidated_code_; | |
974 | 971 |
975 SmartPointer<FreeList> free_list_old_space_; | 972 SmartPointer<FreeList> free_list_old_space_; |
976 | 973 |
977 friend class Heap; | 974 friend class Heap; |
978 }; | 975 }; |
979 | 976 |
980 | 977 |
981 class MarkBitCellIterator BASE_EMBEDDED { | 978 class MarkBitCellIterator BASE_EMBEDDED { |
982 public: | 979 public: |
983 explicit MarkBitCellIterator(MemoryChunk* chunk) : chunk_(chunk) { | 980 explicit MarkBitCellIterator(MemoryChunk* chunk) : chunk_(chunk) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 private: | 1028 private: |
1032 MarkCompactCollector* collector_; | 1029 MarkCompactCollector* collector_; |
1033 }; | 1030 }; |
1034 | 1031 |
1035 | 1032 |
1036 const char* AllocationSpaceName(AllocationSpace space); | 1033 const char* AllocationSpaceName(AllocationSpace space); |
1037 } | 1034 } |
1038 } // namespace v8::internal | 1035 } // namespace v8::internal |
1039 | 1036 |
1040 #endif // V8_HEAP_MARK_COMPACT_H_ | 1037 #endif // V8_HEAP_MARK_COMPACT_H_ |
OLD | NEW |