| 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/assembler.h" | 8 #include "src/assembler.h" |
| 9 #include "src/heap/heap.h" | 9 #include "src/heap/heap.h" |
| 10 #include "src/heap/slot-set.h" | 10 #include "src/heap/slot-set.h" |
| 11 #include "src/heap/spaces.h" | 11 #include "src/heap/spaces.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 enum PointerDirection { OLD_TO_OLD, OLD_TO_NEW }; | 16 enum PointerDirection { OLD_TO_OLD, OLD_TO_NEW }; |
| 17 | 17 |
| 18 // TODO(ulan): Investigate performance of de-templatizing this class. | 18 // TODO(ulan): Investigate performance of de-templatizing this class. |
| 19 template <PointerDirection direction> | 19 template <PointerDirection direction> |
| 20 class RememberedSet { | 20 class RememberedSet { |
| 21 public: | 21 public: |
| 22 // 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 |
| 23 // remembered set. | 23 // remembered set. |
| 24 static void Insert(Page* page, Address slot_addr) { | 24 static void Insert(MemoryChunk* chunk, Address slot_addr) { |
| 25 DCHECK(page->Contains(slot_addr)); | 25 DCHECK(chunk->Contains(slot_addr)); |
| 26 SlotSet* slot_set = GetSlotSet(page); | 26 SlotSet* slot_set = GetSlotSet(chunk); |
| 27 if (slot_set == nullptr) { | 27 if (slot_set == nullptr) { |
| 28 slot_set = AllocateSlotSet(page); | 28 slot_set = AllocateSlotSet(chunk); |
| 29 } | 29 } |
| 30 uintptr_t offset = slot_addr - page->address(); | 30 uintptr_t offset = slot_addr - chunk->address(); |
| 31 slot_set[offset / Page::kPageSize].Insert(offset % Page::kPageSize); | 31 slot_set[offset / Page::kPageSize].Insert(offset % Page::kPageSize); |
| 32 } | 32 } |
| 33 | 33 |
| 34 // Given a page and a slot in that page, this function removes the slot from | 34 // Given a page and a slot in that page, this function removes the slot from |
| 35 // the remembered set. | 35 // the remembered set. |
| 36 // If the slot was never added, then the function does nothing. | 36 // If the slot was never added, then the function does nothing. |
| 37 static void Remove(Page* page, Address slot_addr) { | 37 static void Remove(MemoryChunk* chunk, Address slot_addr) { |
| 38 DCHECK(page->Contains(slot_addr)); | 38 DCHECK(chunk->Contains(slot_addr)); |
| 39 SlotSet* slot_set = GetSlotSet(page); | 39 SlotSet* slot_set = GetSlotSet(chunk); |
| 40 if (slot_set != nullptr) { | 40 if (slot_set != nullptr) { |
| 41 uintptr_t offset = slot_addr - page->address(); | 41 uintptr_t offset = slot_addr - chunk->address(); |
| 42 slot_set[offset / Page::kPageSize].Remove(offset % Page::kPageSize); | 42 slot_set[offset / Page::kPageSize].Remove(offset % Page::kPageSize); |
| 43 } | 43 } |
| 44 } | 44 } |
| 45 | 45 |
| 46 // Given a page and a range of slots in that page, this function removes the | 46 // Given a page and a range of slots in that page, this function removes the |
| 47 // slots from the remembered set. | 47 // slots from the remembered set. |
| 48 static void RemoveRange(Page* page, Address start, Address end) { | 48 static void RemoveRange(MemoryChunk* chunk, Address start, Address end) { |
| 49 SlotSet* slot_set = GetSlotSet(page); | 49 SlotSet* slot_set = GetSlotSet(chunk); |
| 50 if (slot_set != nullptr) { | 50 if (slot_set != nullptr) { |
| 51 uintptr_t start_offset = start - page->address(); | 51 uintptr_t start_offset = start - chunk->address(); |
| 52 uintptr_t end_offset = end - page->address(); | 52 uintptr_t end_offset = end - chunk->address(); |
| 53 DCHECK_LT(start_offset, end_offset); | 53 DCHECK_LT(start_offset, end_offset); |
| 54 DCHECK_LE(end_offset, static_cast<uintptr_t>(Page::kPageSize)); | 54 if (end_offset < static_cast<uintptr_t>(Page::kPageSize)) { |
| 55 slot_set->RemoveRange(static_cast<uint32_t>(start_offset), | 55 slot_set->RemoveRange(static_cast<int>(start_offset), |
| 56 static_cast<uint32_t>(end_offset)); | 56 static_cast<int>(end_offset)); |
| 57 } else { |
| 58 // The large page has multiple slot sets. |
| 59 // Compute slot set indicies for the range [start_offset, end_offset). |
| 60 int start_chunk = static_cast<int>(start_offset / Page::kPageSize); |
| 61 int end_chunk = static_cast<int>((end_offset - 1) / Page::kPageSize); |
| 62 int offset_in_start_chunk = |
| 63 static_cast<int>(start_offset % Page::kPageSize); |
| 64 // Note that using end_offset % Page::kPageSize would be incorrect |
| 65 // because end_offset is one beyond the last slot to clear. |
| 66 int offset_in_end_chunk = static_cast<int>( |
| 67 end_offset - static_cast<uintptr_t>(end_chunk) * Page::kPageSize); |
| 68 if (start_chunk == end_chunk) { |
| 69 slot_set[start_chunk].RemoveRange(offset_in_start_chunk, |
| 70 offset_in_end_chunk); |
| 71 } else { |
| 72 // Clear all slots from start_offset to the end of first chunk. |
| 73 slot_set[start_chunk].RemoveRange(offset_in_start_chunk, |
| 74 Page::kPageSize); |
| 75 // Clear all slots in intermediate chunks. |
| 76 for (int i = start_chunk + 1; i < end_chunk; i++) { |
| 77 slot_set[i].RemoveRange(0, Page::kPageSize); |
| 78 } |
| 79 // Clear slots from the beginning of the last page to end_offset. |
| 80 slot_set[end_chunk].RemoveRange(0, offset_in_end_chunk); |
| 81 } |
| 82 } |
| 57 } | 83 } |
| 58 } | 84 } |
| 59 | 85 |
| 60 // Iterates and filters the remembered set with the given callback. | 86 // Iterates and filters the remembered set with the given callback. |
| 61 // The callback should take (Address slot) and return SlotCallbackResult. | 87 // The callback should take (Address slot) and return SlotCallbackResult. |
| 62 template <typename Callback> | 88 template <typename Callback> |
| 63 static void Iterate(Heap* heap, Callback callback) { | 89 static void Iterate(Heap* heap, Callback callback) { |
| 64 IterateMemoryChunks( | 90 IterateMemoryChunks( |
| 65 heap, [callback](MemoryChunk* chunk) { Iterate(chunk, callback); }); | 91 heap, [callback](MemoryChunk* chunk) { Iterate(chunk, callback); }); |
| 66 } | 92 } |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 return DEBUG_TARGET_SLOT; | 382 return DEBUG_TARGET_SLOT; |
| 357 } | 383 } |
| 358 UNREACHABLE(); | 384 UNREACHABLE(); |
| 359 return NUMBER_OF_SLOT_TYPES; | 385 return NUMBER_OF_SLOT_TYPES; |
| 360 } | 386 } |
| 361 | 387 |
| 362 } // namespace internal | 388 } // namespace internal |
| 363 } // namespace v8 | 389 } // namespace v8 |
| 364 | 390 |
| 365 #endif // V8_REMEMBERED_SET_H | 391 #endif // V8_REMEMBERED_SET_H |
| OLD | NEW |