Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: src/heap/remembered-set.h

Issue 2003553002: [heap] Introduce a new remembered set for typed pointers from old to new. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove the mode of the MemoryChunkIterator. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/assembler.h"
8 #include "src/heap/heap.h" 9 #include "src/heap/heap.h"
9 #include "src/heap/slot-set.h" 10 #include "src/heap/slot-set.h"
10 #include "src/heap/spaces.h" 11 #include "src/heap/spaces.h"
11 12
12 namespace v8 { 13 namespace v8 {
13 namespace internal { 14 namespace internal {
14 15
15 enum PointerDirection { OLD_TO_OLD, OLD_TO_NEW }; 16 enum PointerDirection { OLD_TO_OLD, OLD_TO_NEW };
16 17
17 template <PointerDirection direction> 18 template <PointerDirection direction>
titzer 2016/05/20 11:47:36 (meta question) Does this class really need to be
ulan 2016/05/20 12:48:12 Insertion is performance critical. Run-time check
ahaas 2016/05/20 13:20:16 Done.
18 class RememberedSet { 19 class RememberedSet {
19 public: 20 public:
20 // Given a page and a slot in that page, this function adds the slot to the 21 // Given a page and a slot in that page, this function adds the slot to the
21 // remembered set. 22 // remembered set.
22 static void Insert(Page* page, Address slot_addr) { 23 static void Insert(Page* page, Address slot_addr) {
23 DCHECK(page->Contains(slot_addr)); 24 DCHECK(page->Contains(slot_addr));
24 SlotSet* slot_set = GetSlotSet(page); 25 SlotSet* slot_set = GetSlotSet(page);
25 if (slot_set == nullptr) { 26 if (slot_set == nullptr) {
26 slot_set = AllocateSlotSet(page); 27 slot_set = AllocateSlotSet(page);
27 } 28 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 template <typename Callback> 61 template <typename Callback>
61 static void Iterate(Heap* heap, Callback callback) { 62 static void Iterate(Heap* heap, Callback callback) {
62 IterateMemoryChunks( 63 IterateMemoryChunks(
63 heap, [callback](MemoryChunk* chunk) { Iterate(chunk, callback); }); 64 heap, [callback](MemoryChunk* chunk) { Iterate(chunk, callback); });
64 } 65 }
65 66
66 // Iterates over all memory chunks that contains non-empty slot sets. 67 // Iterates over all memory chunks that contains non-empty slot sets.
67 // The callback should take (MemoryChunk* chunk) and return void. 68 // The callback should take (MemoryChunk* chunk) and return void.
68 template <typename Callback> 69 template <typename Callback>
69 static void IterateMemoryChunks(Heap* heap, Callback callback) { 70 static void IterateMemoryChunks(Heap* heap, Callback callback) {
70 MemoryChunkIterator it(heap, direction == OLD_TO_OLD 71 MemoryChunkIterator it(heap);
71 ? MemoryChunkIterator::ALL
72 : MemoryChunkIterator::ALL_BUT_CODE_SPACE);
73 MemoryChunk* chunk; 72 MemoryChunk* chunk;
74 while ((chunk = it.next()) != nullptr) { 73 while ((chunk = it.next()) != nullptr) {
75 SlotSet* slots = GetSlotSet(chunk); 74 SlotSet* slots = GetSlotSet(chunk);
76 TypedSlotSet* typed_slots = GetTypedSlotSet(chunk); 75 TypedSlotSet* typed_slots = GetTypedSlotSet(chunk);
77 if (slots != nullptr || typed_slots != nullptr) { 76 if (slots != nullptr || typed_slots != nullptr) {
78 callback(chunk); 77 callback(chunk);
79 } 78 }
80 } 79 }
81 } 80 }
82 81
(...skipping 11 matching lines...) Expand all
94 } 93 }
95 if (new_count == 0) { 94 if (new_count == 0) {
96 ReleaseSlotSet(chunk); 95 ReleaseSlotSet(chunk);
97 } 96 }
98 } 97 }
99 } 98 }
100 99
101 // Given a page and a typed slot in that page, this function adds the slot 100 // Given a page and a typed slot in that page, this function adds the slot
102 // to the remembered set. 101 // to the remembered set.
103 static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) { 102 static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) {
104 STATIC_ASSERT(direction == OLD_TO_OLD); 103 TypedSlotSet* slot_set = GetTypedSlotSet(page);
105 TypedSlotSet* slot_set = page->typed_old_to_old_slots();
106 if (slot_set == nullptr) { 104 if (slot_set == nullptr) {
107 page->AllocateTypedOldToOldSlots(); 105 AllocateTypedSlotSet(page);
108 slot_set = page->typed_old_to_old_slots(); 106 slot_set = GetTypedSlotSet(page);
109 } 107 }
110 uintptr_t offset = slot_addr - page->address(); 108 uintptr_t offset = slot_addr - page->address();
111 DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset)); 109 DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset));
112 slot_set->Insert(slot_type, static_cast<uint32_t>(offset)); 110 slot_set->Insert(slot_type, static_cast<uint32_t>(offset));
113 } 111 }
114 112
115 // Given a page and a range of typed slots in that page, this function removes 113 // Given a page and a range of typed slots in that page, this function removes
116 // the slots from the remembered set. 114 // the slots from the remembered set.
117 static void RemoveRangeTyped(Page* page, Address start, Address end) { 115 static void RemoveRangeTyped(Page* page, Address start, Address end) {
118 TypedSlotSet* slots = page->typed_old_to_old_slots(); 116 TypedSlotSet* slots = GetTypedSlotSet(page);
119 if (slots != nullptr) { 117 if (slots != nullptr) {
120 slots->Iterate([start, end](SlotType slot_type, Address slot_addr) { 118 slots->Iterate([start, end](SlotType slot_type, Address slot_addr) {
121 return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT; 119 return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT;
122 }); 120 });
123 } 121 }
124 } 122 }
125 123
124 // Iterates and filters the remembered set with the given callback.
125 // The callback should take (SlotType slot_type, SlotAddress slot) and return
126 // SlotCallbackResult.
127 template <typename Callback>
128 static void IterateTyped(Heap* heap, Callback callback) {
129 IterateMemoryChunks(heap, [callback](MemoryChunk* chunk) {
130 IterateTyped(chunk, callback);
131 });
132 }
133
126 // Iterates and filters typed old to old pointers in the given memory chunk 134 // Iterates and filters typed old to old pointers in the given memory chunk
127 // with the given callback. The callback should take (SlotType slot_type, 135 // with the given callback. The callback should take (SlotType slot_type,
128 // Address slot_addr) and return SlotCallbackResult. 136 // Address slot_addr) and return SlotCallbackResult.
129 template <typename Callback> 137 template <typename Callback>
130 static void IterateTyped(MemoryChunk* chunk, Callback callback) { 138 static void IterateTyped(MemoryChunk* chunk, Callback callback) {
131 TypedSlotSet* slots = chunk->typed_old_to_old_slots(); 139 TypedSlotSet* slots = GetTypedSlotSet(chunk);
132 if (slots != nullptr) { 140 if (slots != nullptr) {
133 int new_count = slots->Iterate(callback); 141 int new_count = slots->Iterate(callback);
134 if (new_count == 0) { 142 if (new_count == 0) {
143 ReleaseTypedSlotSet(chunk);
135 chunk->ReleaseTypedOldToOldSlots(); 144 chunk->ReleaseTypedOldToOldSlots();
136 } 145 }
137 } 146 }
138 } 147 }
139 148
140 // Clear all old to old slots from the remembered set. 149 // Clear all old to old slots from the remembered set.
141 static void ClearAll(Heap* heap) { 150 static void ClearAll(Heap* heap) {
142 STATIC_ASSERT(direction == OLD_TO_OLD); 151 STATIC_ASSERT(direction == OLD_TO_OLD);
143 MemoryChunkIterator it(heap, MemoryChunkIterator::ALL); 152 MemoryChunkIterator it(heap);
144 MemoryChunk* chunk; 153 MemoryChunk* chunk;
145 while ((chunk = it.next()) != nullptr) { 154 while ((chunk = it.next()) != nullptr) {
146 chunk->ReleaseOldToOldSlots(); 155 chunk->ReleaseOldToOldSlots();
147 chunk->ReleaseTypedOldToOldSlots(); 156 chunk->ReleaseTypedOldToOldSlots();
148 } 157 }
149 } 158 }
150 159
151 // Eliminates all stale slots from the remembered set, i.e. 160 // Eliminates all stale slots from the remembered set, i.e.
152 // slots that are not part of live objects anymore. This method must be 161 // slots that are not part of live objects anymore. This method must be
153 // called after marking, when the whole transitive closure is known and 162 // called after marking, when the whole transitive closure is known and
154 // must be called before sweeping when mark bits are still intact. 163 // must be called before sweeping when mark bits are still intact.
155 static void ClearInvalidSlots(Heap* heap); 164 static void ClearInvalidSlots(Heap* heap);
156 165
157 static void VerifyValidSlots(Heap* heap); 166 static void VerifyValidSlots(Heap* heap);
158 167
159 private: 168 private:
160 static SlotSet* GetSlotSet(MemoryChunk* chunk) { 169 static SlotSet* GetSlotSet(MemoryChunk* chunk) {
161 if (direction == OLD_TO_OLD) { 170 if (direction == OLD_TO_OLD) {
162 return chunk->old_to_old_slots(); 171 return chunk->old_to_old_slots();
163 } else { 172 } else {
164 return chunk->old_to_new_slots(); 173 return chunk->old_to_new_slots();
165 } 174 }
166 } 175 }
167 176
168 static TypedSlotSet* GetTypedSlotSet(MemoryChunk* chunk) { 177 static TypedSlotSet* GetTypedSlotSet(MemoryChunk* chunk) {
169 if (direction == OLD_TO_OLD) { 178 if (direction == OLD_TO_OLD) {
170 return chunk->typed_old_to_old_slots(); 179 return chunk->typed_old_to_old_slots();
171 } else { 180 } else {
172 return nullptr; 181 return chunk->typed_old_to_new_slots();
173 } 182 }
174 } 183 }
175 184
176 static void ReleaseSlotSet(MemoryChunk* chunk) { 185 static void ReleaseSlotSet(MemoryChunk* chunk) {
177 if (direction == OLD_TO_OLD) { 186 if (direction == OLD_TO_OLD) {
178 chunk->ReleaseOldToOldSlots(); 187 chunk->ReleaseOldToOldSlots();
179 } else { 188 } else {
180 chunk->ReleaseOldToNewSlots(); 189 chunk->ReleaseOldToNewSlots();
181 } 190 }
182 } 191 }
183 192
193 static void ReleaseTypedSlotSet(MemoryChunk* chunk) {
194 if (direction == OLD_TO_OLD) {
195 chunk->ReleaseTypedOldToOldSlots();
196 } else {
197 chunk->ReleaseTypedOldToNewSlots();
198 }
199 }
200
184 static SlotSet* AllocateSlotSet(MemoryChunk* chunk) { 201 static SlotSet* AllocateSlotSet(MemoryChunk* chunk) {
185 if (direction == OLD_TO_OLD) { 202 if (direction == OLD_TO_OLD) {
186 chunk->AllocateOldToOldSlots(); 203 chunk->AllocateOldToOldSlots();
187 return chunk->old_to_old_slots(); 204 return chunk->old_to_old_slots();
188 } else { 205 } else {
189 chunk->AllocateOldToNewSlots(); 206 chunk->AllocateOldToNewSlots();
190 return chunk->old_to_new_slots(); 207 return chunk->old_to_new_slots();
191 } 208 }
192 } 209 }
193 210
211 static TypedSlotSet* AllocateTypedSlotSet(MemoryChunk* chunk) {
212 if (direction == OLD_TO_OLD) {
213 chunk->AllocateTypedOldToOldSlots();
214 return chunk->typed_old_to_old_slots();
215 } else {
216 chunk->AllocateTypedOldToNewSlots();
217 return chunk->typed_old_to_new_slots();
218 }
219 }
220
194 static bool IsValidSlot(Heap* heap, MemoryChunk* chunk, Object** slot); 221 static bool IsValidSlot(Heap* heap, MemoryChunk* chunk, Object** slot);
195 }; 222 };
196 223
224 class UpdateTypedSlotHelper {
225 public:
226 // Updates a cell slot using an untyped slot callback.
227 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
228 template <typename Callback>
229 static SlotCallbackResult UpdateCell(RelocInfo* rinfo, Callback callback) {
230 DCHECK(rinfo->rmode() == RelocInfo::CELL);
231 Object* cell = rinfo->target_cell();
232 Object* old_cell = cell;
233 SlotCallbackResult result = callback(&cell);
234 if (cell != old_cell) {
235 rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
236 }
237 return result;
238 }
239
240 // Updates a code entry slot using an untyped slot callback.
241 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
242 template <typename Callback>
243 static SlotCallbackResult UpdateCodeEntry(Address entry_address,
244 Callback callback) {
245 Object* code = Code::GetObjectFromEntryAddress(entry_address);
246 Object* old_code = code;
247 SlotCallbackResult result = callback(&code);
248 if (code != old_code) {
249 Memory::Address_at(entry_address) =
250 reinterpret_cast<Code*>(code)->entry();
251 }
252 return result;
253 }
254
255 // Updates a code target slot using an untyped slot callback.
256 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
257 template <typename Callback>
258 static SlotCallbackResult UpdateCodeTarget(RelocInfo* rinfo,
259 Callback callback) {
260 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
261 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
262 Object* old_target = target;
263 SlotCallbackResult result = callback(&target);
264 if (target != old_target) {
265 rinfo->set_target_address(Code::cast(target)->instruction_start());
266 }
267 return result;
268 }
269
270 // Updates an embedded pointer slot using an untyped slot callback.
271 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
272 template <typename Callback>
273 static SlotCallbackResult UpdateEmbeddedPointer(RelocInfo* rinfo,
274 Callback callback) {
275 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
276 Object* target = rinfo->target_object();
277 Object* old_target = target;
278 SlotCallbackResult result = callback(&target);
279 if (target != old_target) {
280 rinfo->set_target_object(target);
281 }
282 return result;
283 }
284
285 // Updates a debug target slot using an untyped slot callback.
286 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
287 template <typename Callback>
288 static SlotCallbackResult UpdateDebugTarget(RelocInfo* rinfo,
289 Callback callback) {
290 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
291 rinfo->IsPatchedDebugBreakSlotSequence());
292 Object* target =
293 Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
294 SlotCallbackResult result = callback(&target);
295 rinfo->set_debug_call_address(Code::cast(target)->instruction_start());
296 return result;
297 }
298
299 // Updates a typed slot using an untyped slot callback.
300 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
301 template <typename Callback>
302 static SlotCallbackResult UpdateTypedSlot(Isolate* isolate,
303 SlotType slot_type, Address addr,
304 Callback callback) {
305 switch (slot_type) {
306 case CODE_TARGET_SLOT: {
307 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL);
308 return UpdateCodeTarget(&rinfo, callback);
309 }
310 case CELL_TARGET_SLOT: {
311 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL);
312 return UpdateCell(&rinfo, callback);
313 }
314 case CODE_ENTRY_SLOT: {
315 return UpdateCodeEntry(addr, callback);
316 }
317 case DEBUG_TARGET_SLOT: {
318 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION,
319 0, NULL);
320 if (rinfo.IsPatchedDebugBreakSlotSequence()) {
321 return UpdateDebugTarget(&rinfo, callback);
322 }
323 return REMOVE_SLOT;
324 }
325 case EMBEDDED_OBJECT_SLOT: {
326 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL);
327 return UpdateEmbeddedPointer(&rinfo, callback);
328 }
329 case OBJECT_SLOT: {
330 return callback(reinterpret_cast<Object**>(addr));
331 }
332 case NUMBER_OF_SLOT_TYPES:
333 break;
334 }
335 UNREACHABLE();
336 return REMOVE_SLOT;
337 }
338 };
339
197 } // namespace internal 340 } // namespace internal
198 } // namespace v8 341 } // namespace v8
199 342
200 #endif // V8_REMEMBERED_SET_H 343 #endif // V8_REMEMBERED_SET_H
OLDNEW
« src/heap/mark-compact.cc ('K') | « src/heap/mark-compact.cc ('k') | src/heap/spaces.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698