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