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