OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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_REMEMBERED_SET_H | 5 #ifndef V8_REMEMBERED_SET_H |
6 #define V8_REMEMBERED_SET_H | 6 #define V8_REMEMBERED_SET_H |
7 | 7 |
8 #include "src/heap/heap.h" | 8 #include "src/heap/heap.h" |
9 #include "src/heap/slot-set.h" | 9 #include "src/heap/slot-set.h" |
10 #include "src/heap/spaces.h" | 10 #include "src/heap/spaces.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 DCHECK_LE(end_offset, static_cast<uintptr_t>(Page::kPageSize)); | 52 DCHECK_LE(end_offset, static_cast<uintptr_t>(Page::kPageSize)); |
53 slot_set->RemoveRange(static_cast<uint32_t>(start_offset), | 53 slot_set->RemoveRange(static_cast<uint32_t>(start_offset), |
54 static_cast<uint32_t>(end_offset)); | 54 static_cast<uint32_t>(end_offset)); |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 // Iterates and filters the remembered set with the given callback. | 58 // Iterates and filters the remembered set with the given callback. |
59 // The callback should take (Address slot) and return SlotCallbackResult. | 59 // The callback should take (Address slot) and return SlotCallbackResult. |
60 template <typename Callback> | 60 template <typename Callback> |
61 static void Iterate(Heap* heap, Callback callback) { | 61 static void Iterate(Heap* heap, Callback callback) { |
| 62 IterateMemoryChunks( |
| 63 heap, [callback](MemoryChunk* chunk) { Iterate(chunk, callback); }); |
| 64 } |
| 65 |
| 66 // Iterates over all memory chunks that contains non-empty slot sets. |
| 67 // The callback should take (MemoryChunk* chunk) and return void. |
| 68 template <typename Callback> |
| 69 static void IterateMemoryChunks(Heap* heap, Callback callback) { |
62 MemoryChunkIterator it(heap, direction == OLD_TO_OLD | 70 MemoryChunkIterator it(heap, direction == OLD_TO_OLD |
63 ? MemoryChunkIterator::ALL | 71 ? MemoryChunkIterator::ALL |
64 : MemoryChunkIterator::ALL_BUT_CODE_SPACE); | 72 : MemoryChunkIterator::ALL_BUT_CODE_SPACE); |
65 MemoryChunk* chunk; | 73 MemoryChunk* chunk; |
66 while ((chunk = it.next()) != nullptr) { | 74 while ((chunk = it.next()) != nullptr) { |
67 SlotSet* slots = GetSlotSet(chunk); | 75 SlotSet* slots = GetSlotSet(chunk); |
68 if (slots != nullptr) { | 76 TypedSlotSet* typed_slots = GetTypedSlotSet(chunk); |
69 size_t pages = (chunk->size() + Page::kPageSize - 1) / Page::kPageSize; | 77 if (slots != nullptr || typed_slots != nullptr) { |
70 int new_count = 0; | 78 callback(chunk); |
71 for (size_t page = 0; page < pages; page++) { | |
72 new_count += slots[page].Iterate(callback); | |
73 } | |
74 if (new_count == 0) { | |
75 ReleaseSlotSet(chunk); | |
76 } | |
77 } | 79 } |
78 } | 80 } |
79 } | 81 } |
| 82 |
| 83 // Iterates and filters the remembered set in the given memory chunk with |
| 84 // the given callback. The callback should take (Address slot) and return |
| 85 // SlotCallbackResult. |
| 86 template <typename Callback> |
| 87 static void Iterate(MemoryChunk* chunk, Callback callback) { |
| 88 SlotSet* slots = GetSlotSet(chunk); |
| 89 if (slots != nullptr) { |
| 90 size_t pages = (chunk->size() + Page::kPageSize - 1) / Page::kPageSize; |
| 91 int new_count = 0; |
| 92 for (size_t page = 0; page < pages; page++) { |
| 93 new_count += slots[page].Iterate(callback); |
| 94 } |
| 95 if (new_count == 0) { |
| 96 ReleaseSlotSet(chunk); |
| 97 } |
| 98 } |
| 99 } |
80 | 100 |
81 // Iterates and filters the remembered set with the given callback. | 101 // Iterates and filters the remembered set with the given callback. |
82 // The callback should take (HeapObject** slot, HeapObject* target) and | 102 // The callback should take (HeapObject** slot, HeapObject* target) and |
83 // update the slot. | 103 // update the slot. |
84 // A special wrapper takes care of filtering the slots based on their values. | 104 // A special wrapper takes care of filtering the slots based on their values. |
85 // For OLD_TO_NEW case: slots that do not point to the ToSpace after | 105 // For OLD_TO_NEW case: slots that do not point to the ToSpace after |
86 // callback invocation will be removed from the set. | 106 // callback invocation will be removed from the set. |
87 template <typename Callback> | 107 template <typename Callback> |
88 static void IterateWithWrapper(Heap* heap, Callback callback) { | 108 static void IterateWithWrapper(Heap* heap, Callback callback) { |
89 Iterate(heap, [heap, callback](Address addr) { | 109 Iterate(heap, [heap, callback](Address addr) { |
90 return Wrapper(heap, addr, callback); | 110 return Wrapper(heap, addr, callback); |
91 }); | 111 }); |
92 } | 112 } |
93 | 113 |
| 114 template <typename Callback> |
| 115 static void IterateWithWrapper(Heap* heap, MemoryChunk* chunk, |
| 116 Callback callback) { |
| 117 Iterate(chunk, [heap, callback](Address addr) { |
| 118 return Wrapper(heap, addr, callback); |
| 119 }); |
| 120 } |
| 121 |
94 // Given a page and a typed slot in that page, this function adds the slot | 122 // Given a page and a typed slot in that page, this function adds the slot |
95 // to the remembered set. | 123 // to the remembered set. |
96 static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) { | 124 static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) { |
97 STATIC_ASSERT(direction == OLD_TO_OLD); | 125 STATIC_ASSERT(direction == OLD_TO_OLD); |
98 TypedSlotSet* slot_set = page->typed_old_to_old_slots(); | 126 TypedSlotSet* slot_set = page->typed_old_to_old_slots(); |
99 if (slot_set == nullptr) { | 127 if (slot_set == nullptr) { |
100 page->AllocateTypedOldToOldSlots(); | 128 page->AllocateTypedOldToOldSlots(); |
101 slot_set = page->typed_old_to_old_slots(); | 129 slot_set = page->typed_old_to_old_slots(); |
102 } | 130 } |
103 uintptr_t offset = slot_addr - page->address(); | 131 uintptr_t offset = slot_addr - page->address(); |
104 DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset)); | 132 DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset)); |
105 slot_set->Insert(slot_type, static_cast<uint32_t>(offset)); | 133 slot_set->Insert(slot_type, static_cast<uint32_t>(offset)); |
106 } | 134 } |
107 | 135 |
108 // Given a page and a range of typed slots in that page, this function removes | 136 // Given a page and a range of typed slots in that page, this function removes |
109 // the slots from the remembered set. | 137 // the slots from the remembered set. |
110 static void RemoveRangeTyped(Page* page, Address start, Address end) { | 138 static void RemoveRangeTyped(Page* page, Address start, Address end) { |
111 TypedSlotSet* slots = page->typed_old_to_old_slots(); | 139 TypedSlotSet* slots = page->typed_old_to_old_slots(); |
112 if (slots != nullptr) { | 140 if (slots != nullptr) { |
113 slots->Iterate([start, end](SlotType slot_type, Address slot_addr) { | 141 slots->Iterate([start, end](SlotType slot_type, Address slot_addr) { |
114 return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT; | 142 return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT; |
115 }); | 143 }); |
116 } | 144 } |
117 } | 145 } |
118 | 146 |
119 // Iterates and filters typed old to old pointers with the given callback. | 147 // Iterates and filters typed old to old pointers in the given memory chunk |
120 // The callback should take (SlotType slot_type, Address slot_addr) and | 148 // with the given callback. The callback should take (SlotType slot_type, |
121 // return SlotCallbackResult. | 149 // Address slot_addr) and return SlotCallbackResult. |
122 template <typename Callback> | 150 template <typename Callback> |
123 static void IterateTyped(Heap* heap, Callback callback) { | 151 static void IterateTyped(MemoryChunk* chunk, Callback callback) { |
124 MemoryChunkIterator it(heap, MemoryChunkIterator::ALL_BUT_MAP_SPACE); | 152 TypedSlotSet* slots = chunk->typed_old_to_old_slots(); |
125 MemoryChunk* chunk; | 153 if (slots != nullptr) { |
126 while ((chunk = it.next()) != nullptr) { | 154 int new_count = slots->Iterate(callback); |
127 TypedSlotSet* slots = chunk->typed_old_to_old_slots(); | 155 if (new_count == 0) { |
128 if (slots != nullptr) { | 156 chunk->ReleaseTypedOldToOldSlots(); |
129 int new_count = slots->Iterate(callback); | |
130 if (new_count == 0) { | |
131 chunk->ReleaseTypedOldToOldSlots(); | |
132 } | |
133 } | 157 } |
134 } | 158 } |
135 } | 159 } |
136 | 160 |
137 // Clear all old to old slots from the remembered set. | 161 // Clear all old to old slots from the remembered set. |
138 static void ClearAll(Heap* heap) { | 162 static void ClearAll(Heap* heap) { |
139 STATIC_ASSERT(direction == OLD_TO_OLD); | 163 STATIC_ASSERT(direction == OLD_TO_OLD); |
140 MemoryChunkIterator it(heap, MemoryChunkIterator::ALL); | 164 MemoryChunkIterator it(heap, MemoryChunkIterator::ALL); |
141 MemoryChunk* chunk; | 165 MemoryChunk* chunk; |
142 while ((chunk = it.next()) != nullptr) { | 166 while ((chunk = it.next()) != nullptr) { |
(...skipping 12 matching lines...) Expand all Loading... |
155 | 179 |
156 private: | 180 private: |
157 static SlotSet* GetSlotSet(MemoryChunk* chunk) { | 181 static SlotSet* GetSlotSet(MemoryChunk* chunk) { |
158 if (direction == OLD_TO_OLD) { | 182 if (direction == OLD_TO_OLD) { |
159 return chunk->old_to_old_slots(); | 183 return chunk->old_to_old_slots(); |
160 } else { | 184 } else { |
161 return chunk->old_to_new_slots(); | 185 return chunk->old_to_new_slots(); |
162 } | 186 } |
163 } | 187 } |
164 | 188 |
| 189 static TypedSlotSet* GetTypedSlotSet(MemoryChunk* chunk) { |
| 190 if (direction == OLD_TO_OLD) { |
| 191 return chunk->typed_old_to_old_slots(); |
| 192 } else { |
| 193 return nullptr; |
| 194 } |
| 195 } |
| 196 |
165 static void ReleaseSlotSet(MemoryChunk* chunk) { | 197 static void ReleaseSlotSet(MemoryChunk* chunk) { |
166 if (direction == OLD_TO_OLD) { | 198 if (direction == OLD_TO_OLD) { |
167 chunk->ReleaseOldToOldSlots(); | 199 chunk->ReleaseOldToOldSlots(); |
168 } else { | 200 } else { |
169 chunk->ReleaseOldToNewSlots(); | 201 chunk->ReleaseOldToNewSlots(); |
170 } | 202 } |
171 } | 203 } |
172 | 204 |
173 static SlotSet* AllocateSlotSet(MemoryChunk* chunk) { | 205 static SlotSet* AllocateSlotSet(MemoryChunk* chunk) { |
174 if (direction == OLD_TO_OLD) { | 206 if (direction == OLD_TO_OLD) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 int count; | 316 int count; |
285 }; | 317 }; |
286 | 318 |
287 Node* top_; | 319 Node* top_; |
288 }; | 320 }; |
289 | 321 |
290 } // namespace internal | 322 } // namespace internal |
291 } // namespace v8 | 323 } // namespace v8 |
292 | 324 |
293 #endif // V8_REMEMBERED_SET_H | 325 #endif // V8_REMEMBERED_SET_H |
OLD | NEW |