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 |