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