| 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 <deque> | 8 #include <deque> |
| 9 | 9 |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 // Callback function to mark an object in a given heap. | 25 // Callback function to mark an object in a given heap. |
| 26 typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object); | 26 typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object); |
| 27 | 27 |
| 28 // Forward declarations. | 28 // Forward declarations. |
| 29 class CodeFlusher; | 29 class CodeFlusher; |
| 30 class HeapObjectVisitor; | 30 class HeapObjectVisitor; |
| 31 class MarkCompactCollector; | 31 class MarkCompactCollector; |
| 32 class MinorMarkCompactCollector; | 32 class MinorMarkCompactCollector; |
| 33 class MarkingVisitor; | 33 class MarkingVisitor; |
| 34 | 34 |
| 35 class MarkingState { | |
| 36 public: | |
| 37 static MarkingState FromPageInternal(MemoryChunk* chunk) { | |
| 38 return MarkingState(chunk->markbits<MarkingMode::FULL>(), | |
| 39 chunk->live_bytes_address<MarkingMode::FULL>()); | |
| 40 } | |
| 41 | |
| 42 static MarkingState FromPageExternal(MemoryChunk* chunk) { | |
| 43 return MarkingState( | |
| 44 chunk->markbits<MarkingMode::YOUNG_GENERATION>(), | |
| 45 chunk->live_bytes_address<MarkingMode::YOUNG_GENERATION>()); | |
| 46 } | |
| 47 | |
| 48 MarkingState(Bitmap* bitmap, intptr_t* live_bytes) | |
| 49 : bitmap(bitmap), live_bytes(live_bytes) {} | |
| 50 | |
| 51 void IncrementLiveBytes(intptr_t by) const { | |
| 52 *live_bytes += static_cast<int>(by); | |
| 53 } | |
| 54 void SetLiveBytes(intptr_t value) const { | |
| 55 *live_bytes = static_cast<int>(value); | |
| 56 } | |
| 57 | |
| 58 void ClearLiveness() const { | |
| 59 bitmap->Clear(); | |
| 60 *live_bytes = 0; | |
| 61 } | |
| 62 | |
| 63 Bitmap* bitmap; | |
| 64 intptr_t* live_bytes; | |
| 65 }; | |
| 66 | |
| 67 // TODO(mlippautz): Remove duplicate accessors once the architecture for | |
| 68 // different markers is fixed. | |
| 69 class ObjectMarking : public AllStatic { | 35 class ObjectMarking : public AllStatic { |
| 70 public: | 36 public: |
| 71 V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj) { | |
| 72 const Address address = obj->address(); | |
| 73 const MemoryChunk* p = MemoryChunk::FromAddress(address); | |
| 74 return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(address)); | |
| 75 } | |
| 76 | |
| 77 V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj, | 37 V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj, |
| 78 const MarkingState& state) { | 38 const MarkingState& state) { |
| 79 const Address address = obj->address(); | 39 const Address address = obj->address(); |
| 80 const MemoryChunk* p = MemoryChunk::FromAddress(address); | 40 const MemoryChunk* p = MemoryChunk::FromAddress(address); |
| 81 return state.bitmap->MarkBitFromIndex(p->AddressToMarkbitIndex(address)); | 41 return state.bitmap()->MarkBitFromIndex(p->AddressToMarkbitIndex(address)); |
| 82 } | |
| 83 | |
| 84 static Marking::ObjectColor Color(HeapObject* obj) { | |
| 85 return Marking::Color(ObjectMarking::MarkBitFrom(obj)); | |
| 86 } | 42 } |
| 87 | 43 |
| 88 static Marking::ObjectColor Color(HeapObject* obj, | 44 static Marking::ObjectColor Color(HeapObject* obj, |
| 89 const MarkingState& state) { | 45 const MarkingState& state) { |
| 90 return Marking::Color(ObjectMarking::MarkBitFrom(obj, state)); | 46 return Marking::Color(ObjectMarking::MarkBitFrom(obj, state)); |
| 91 } | 47 } |
| 92 | 48 |
| 93 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 49 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 94 V8_INLINE static bool IsImpossible(HeapObject* obj) { | |
| 95 return Marking::IsImpossible<access_mode>(MarkBitFrom(obj)); | |
| 96 } | |
| 97 | |
| 98 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 99 V8_INLINE static bool IsImpossible(HeapObject* obj, | 50 V8_INLINE static bool IsImpossible(HeapObject* obj, |
| 100 const MarkingState& state) { | 51 const MarkingState& state) { |
| 101 return Marking::IsImpossible<access_mode>(MarkBitFrom(obj, state)); | 52 return Marking::IsImpossible<access_mode>(MarkBitFrom(obj, state)); |
| 102 } | 53 } |
| 103 | 54 |
| 104 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 55 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 105 V8_INLINE static bool IsBlack(HeapObject* obj) { | |
| 106 return Marking::IsBlack<access_mode>(MarkBitFrom(obj)); | |
| 107 } | |
| 108 | |
| 109 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 110 V8_INLINE static bool IsBlack(HeapObject* obj, const MarkingState& state) { | 56 V8_INLINE static bool IsBlack(HeapObject* obj, const MarkingState& state) { |
| 111 return Marking::IsBlack<access_mode>(MarkBitFrom(obj, state)); | 57 return Marking::IsBlack<access_mode>(MarkBitFrom(obj, state)); |
| 112 } | 58 } |
| 113 | 59 |
| 114 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 60 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 115 V8_INLINE static bool IsWhite(HeapObject* obj) { | |
| 116 return Marking::IsWhite<access_mode>(MarkBitFrom(obj)); | |
| 117 } | |
| 118 | |
| 119 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 120 V8_INLINE static bool IsWhite(HeapObject* obj, const MarkingState& state) { | 61 V8_INLINE static bool IsWhite(HeapObject* obj, const MarkingState& state) { |
| 121 return Marking::IsWhite<access_mode>(MarkBitFrom(obj, state)); | 62 return Marking::IsWhite<access_mode>(MarkBitFrom(obj, state)); |
| 122 } | 63 } |
| 123 | 64 |
| 124 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 65 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 125 V8_INLINE static bool IsGrey(HeapObject* obj) { | |
| 126 return Marking::IsGrey<access_mode>(MarkBitFrom(obj)); | |
| 127 } | |
| 128 | |
| 129 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 130 V8_INLINE static bool IsGrey(HeapObject* obj, const MarkingState& state) { | 66 V8_INLINE static bool IsGrey(HeapObject* obj, const MarkingState& state) { |
| 131 return Marking::IsGrey<access_mode>(MarkBitFrom(obj, state)); | 67 return Marking::IsGrey<access_mode>(MarkBitFrom(obj, state)); |
| 132 } | 68 } |
| 133 | 69 |
| 134 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 70 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 135 V8_INLINE static bool IsBlackOrGrey(HeapObject* obj) { | |
| 136 return Marking::IsBlackOrGrey<access_mode>(MarkBitFrom(obj)); | |
| 137 } | |
| 138 | |
| 139 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 140 V8_INLINE static bool IsBlackOrGrey(HeapObject* obj, | 71 V8_INLINE static bool IsBlackOrGrey(HeapObject* obj, |
| 141 const MarkingState& state) { | 72 const MarkingState& state) { |
| 142 return Marking::IsBlackOrGrey<access_mode>(MarkBitFrom(obj, state)); | 73 return Marking::IsBlackOrGrey<access_mode>(MarkBitFrom(obj, state)); |
| 143 } | 74 } |
| 144 | 75 |
| 145 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 76 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 146 V8_INLINE static bool BlackToGrey(HeapObject* obj) { | |
| 147 DCHECK((access_mode == MarkBit::ATOMIC || IsBlack<access_mode>(obj))); | |
| 148 MarkBit markbit = MarkBitFrom(obj); | |
| 149 if (!Marking::BlackToGrey<access_mode>(markbit)) return false; | |
| 150 MemoryChunk::IncrementLiveBytes(obj, -obj->Size()); | |
| 151 return true; | |
| 152 } | |
| 153 | |
| 154 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 155 V8_INLINE static bool BlackToGrey(HeapObject* obj, | 77 V8_INLINE static bool BlackToGrey(HeapObject* obj, |
| 156 const MarkingState& state) { | 78 const MarkingState& state) { |
| 157 DCHECK( | 79 DCHECK( |
| 158 (access_mode == MarkBit::ATOMIC || IsBlack<access_mode>(obj, state))); | 80 (access_mode == MarkBit::ATOMIC || IsBlack<access_mode>(obj, state))); |
| 159 MarkBit markbit = MarkBitFrom(obj, state); | 81 MarkBit markbit = MarkBitFrom(obj, state); |
| 160 if (!Marking::BlackToGrey<access_mode>(markbit)) return false; | 82 if (!Marking::BlackToGrey<access_mode>(markbit)) return false; |
| 161 state.IncrementLiveBytes(-obj->Size()); | 83 state.IncrementLiveBytes(-obj->Size()); |
| 162 return true; | 84 return true; |
| 163 } | 85 } |
| 164 | 86 |
| 165 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 87 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 166 V8_INLINE static bool WhiteToGrey(HeapObject* obj) { | |
| 167 DCHECK((access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj))); | |
| 168 return Marking::WhiteToGrey<access_mode>(MarkBitFrom(obj)); | |
| 169 } | |
| 170 | |
| 171 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 172 V8_INLINE static bool WhiteToGrey(HeapObject* obj, | 88 V8_INLINE static bool WhiteToGrey(HeapObject* obj, |
| 173 const MarkingState& state) { | 89 const MarkingState& state) { |
| 174 DCHECK( | 90 DCHECK( |
| 175 (access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj, state))); | 91 (access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj, state))); |
| 176 return Marking::WhiteToGrey<access_mode>(MarkBitFrom(obj, state)); | 92 return Marking::WhiteToGrey<access_mode>(MarkBitFrom(obj, state)); |
| 177 } | 93 } |
| 178 | 94 |
| 179 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 95 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 180 V8_INLINE static bool WhiteToBlack(HeapObject* obj) { | |
| 181 DCHECK((access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj))); | |
| 182 if (!ObjectMarking::WhiteToGrey<access_mode>(obj)) return false; | |
| 183 return ObjectMarking::GreyToBlack<access_mode>(obj); | |
| 184 } | |
| 185 | |
| 186 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 187 V8_INLINE static bool WhiteToBlack(HeapObject* obj, | 96 V8_INLINE static bool WhiteToBlack(HeapObject* obj, |
| 188 const MarkingState& state) { | 97 const MarkingState& state) { |
| 189 DCHECK( | 98 DCHECK( |
| 190 (access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj, state))); | 99 (access_mode == MarkBit::ATOMIC || IsWhite<access_mode>(obj, state))); |
| 191 if (!ObjectMarking::WhiteToGrey<access_mode>(obj, state)) return false; | 100 if (!ObjectMarking::WhiteToGrey<access_mode>(obj, state)) return false; |
| 192 return ObjectMarking::GreyToBlack<access_mode>(obj, state); | 101 return ObjectMarking::GreyToBlack<access_mode>(obj, state); |
| 193 } | 102 } |
| 194 | 103 |
| 195 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | 104 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> |
| 196 V8_INLINE static bool GreyToBlack(HeapObject* obj) { | |
| 197 DCHECK((access_mode == MarkBit::ATOMIC || IsGrey<access_mode>(obj))); | |
| 198 MarkBit markbit = MarkBitFrom(obj); | |
| 199 if (!Marking::GreyToBlack<access_mode>(markbit)) return false; | |
| 200 MemoryChunk::IncrementLiveBytes(obj, obj->Size()); | |
| 201 return true; | |
| 202 } | |
| 203 | |
| 204 template <MarkBit::AccessMode access_mode = MarkBit::NON_ATOMIC> | |
| 205 V8_INLINE static bool GreyToBlack(HeapObject* obj, | 105 V8_INLINE static bool GreyToBlack(HeapObject* obj, |
| 206 const MarkingState& state) { | 106 const MarkingState& state) { |
| 207 DCHECK((access_mode == MarkBit::ATOMIC || IsGrey<access_mode>(obj, state))); | 107 DCHECK((access_mode == MarkBit::ATOMIC || IsGrey<access_mode>(obj, state))); |
| 208 MarkBit markbit = MarkBitFrom(obj, state); | 108 MarkBit markbit = MarkBitFrom(obj, state); |
| 209 if (!Marking::GreyToBlack<access_mode>(markbit)) return false; | 109 if (!Marking::GreyToBlack<access_mode>(markbit)) return false; |
| 210 state.IncrementLiveBytes(obj->Size()); | 110 state.IncrementLiveBytes(obj->Size()); |
| 211 return true; | 111 return true; |
| 212 } | 112 } |
| 213 | 113 |
| 214 private: | 114 private: |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 class ThreadLocalTop; | 306 class ThreadLocalTop; |
| 407 | 307 |
| 408 class MarkBitCellIterator BASE_EMBEDDED { | 308 class MarkBitCellIterator BASE_EMBEDDED { |
| 409 public: | 309 public: |
| 410 MarkBitCellIterator(MemoryChunk* chunk, MarkingState state) : chunk_(chunk) { | 310 MarkBitCellIterator(MemoryChunk* chunk, MarkingState state) : chunk_(chunk) { |
| 411 last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex( | 311 last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex( |
| 412 chunk_->AddressToMarkbitIndex(chunk_->area_end()))); | 312 chunk_->AddressToMarkbitIndex(chunk_->area_end()))); |
| 413 cell_base_ = chunk_->area_start(); | 313 cell_base_ = chunk_->area_start(); |
| 414 cell_index_ = Bitmap::IndexToCell( | 314 cell_index_ = Bitmap::IndexToCell( |
| 415 Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_))); | 315 Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_))); |
| 416 cells_ = state.bitmap->cells(); | 316 cells_ = state.bitmap()->cells(); |
| 417 } | 317 } |
| 418 | 318 |
| 419 inline bool Done() { return cell_index_ == last_cell_index_; } | 319 inline bool Done() { return cell_index_ == last_cell_index_; } |
| 420 | 320 |
| 421 inline bool HasNext() { return cell_index_ < last_cell_index_ - 1; } | 321 inline bool HasNext() { return cell_index_ < last_cell_index_ - 1; } |
| 422 | 322 |
| 423 inline MarkBit::CellType* CurrentCell() { | 323 inline MarkBit::CellType* CurrentCell() { |
| 424 DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex( | 324 DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex( |
| 425 chunk_->AddressToMarkbitIndex(cell_base_)))); | 325 chunk_->AddressToMarkbitIndex(cell_base_)))); |
| 426 return &cells_[cell_index_]; | 326 return &cells_[cell_index_]; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 : heap_(heap), marking_deque_(heap) {} | 419 : heap_(heap), marking_deque_(heap) {} |
| 520 | 420 |
| 521 void SetUp(); | 421 void SetUp(); |
| 522 void TearDown(); | 422 void TearDown(); |
| 523 | 423 |
| 524 void CollectGarbage(); | 424 void CollectGarbage(); |
| 525 | 425 |
| 526 private: | 426 private: |
| 527 class RootMarkingVisitor; | 427 class RootMarkingVisitor; |
| 528 | 428 |
| 529 static MarkingState StateForObject(HeapObject* object) { | |
| 530 return MarkingState::FromPageExternal(Page::FromAddress(object->address())); | |
| 531 } | |
| 532 | |
| 533 inline Heap* heap() { return heap_; } | 429 inline Heap* heap() { return heap_; } |
| 534 inline Isolate* isolate() { return heap()->isolate(); } | 430 inline Isolate* isolate() { return heap()->isolate(); } |
| 535 inline MarkingDeque* marking_deque() { return &marking_deque_; } | 431 inline MarkingDeque* marking_deque() { return &marking_deque_; } |
| 536 | 432 |
| 537 V8_INLINE void MarkObject(HeapObject* obj); | 433 V8_INLINE void MarkObject(HeapObject* obj); |
| 538 V8_INLINE void PushBlack(HeapObject* obj); | 434 V8_INLINE void PushBlack(HeapObject* obj); |
| 539 | 435 |
| 540 SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address); | 436 SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address); |
| 541 void MarkLiveObjects(); | 437 void MarkLiveObjects(); |
| 542 void ProcessMarkingDeque(); | 438 void ProcessMarkingDeque(); |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 | 860 |
| 965 private: | 861 private: |
| 966 MarkCompactCollector* collector_; | 862 MarkCompactCollector* collector_; |
| 967 }; | 863 }; |
| 968 | 864 |
| 969 V8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space); | 865 V8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space); |
| 970 } // namespace internal | 866 } // namespace internal |
| 971 } // namespace v8 | 867 } // namespace v8 |
| 972 | 868 |
| 973 #endif // V8_HEAP_MARK_COMPACT_H_ | 869 #endif // V8_HEAP_MARK_COMPACT_H_ |
| OLD | NEW |