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

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