Index: src/heap/remembered-set.cc |
diff --git a/src/heap/remembered-set.cc b/src/heap/remembered-set.cc |
index 4e621611ac817abc6d356bba7e237f939014b4a8..c5dab905159b33be62906139efb79b64209ee46e 100644 |
--- a/src/heap/remembered-set.cc |
+++ b/src/heap/remembered-set.cc |
@@ -15,55 +15,93 @@ |
namespace internal { |
template <PointerDirection direction> |
-void RememberedSet<direction>::ClearInvalidSlots(Heap* heap, |
- MemoryChunk* chunk) { |
+void RememberedSet<direction>::ClearInvalidSlots(Heap* heap) { |
STATIC_ASSERT(direction == OLD_TO_NEW); |
- DCHECK(chunk->owner()->identity() == OLD_SPACE || |
- chunk->owner()->identity() == MAP_SPACE); |
- SlotSet* slots = GetSlotSet(chunk); |
- if (slots != nullptr) { |
- slots->Iterate( |
- [heap, chunk](Address addr) { |
- Object** slot = reinterpret_cast<Object**>(addr); |
- return IsValidSlot(heap, chunk, slot) ? KEEP_SLOT : REMOVE_SLOT; |
- }, |
- SlotSet::KEEP_EMPTY_BUCKETS); |
+ for (MemoryChunk* chunk : *heap->old_space()) { |
+ SlotSet* slots = GetSlotSet(chunk); |
+ if (slots != nullptr) { |
+ slots->Iterate( |
+ [heap, chunk](Address addr) { |
+ Object** slot = reinterpret_cast<Object**>(addr); |
+ return IsValidSlot(heap, chunk, slot) ? KEEP_SLOT : REMOVE_SLOT; |
+ }, |
+ SlotSet::PREFREE_EMPTY_BUCKETS); |
+ } |
+ } |
+ for (MemoryChunk* chunk : *heap->code_space()) { |
+ TypedSlotSet* slots = GetTypedSlotSet(chunk); |
+ if (slots != nullptr) { |
+ slots->Iterate( |
+ [heap, chunk](SlotType type, Address host_addr, Address addr) { |
+ if (Marking::IsBlack(ObjectMarking::MarkBitFrom(host_addr))) { |
+ return KEEP_SLOT; |
+ } else { |
+ return REMOVE_SLOT; |
+ } |
+ }, |
+ TypedSlotSet::PREFREE_EMPTY_CHUNKS); |
+ } |
+ } |
+ for (MemoryChunk* chunk : *heap->map_space()) { |
+ SlotSet* slots = GetSlotSet(chunk); |
+ if (slots != nullptr) { |
+ slots->Iterate( |
+ [heap, chunk](Address addr) { |
+ Object** slot = reinterpret_cast<Object**>(addr); |
+ // TODO(mlippautz): In map space all allocations would ideally be |
+ // map |
+ // aligned. After establishing this invariant IsValidSlot could just |
+ // refer to the containing object using alignment and check the mark |
+ // bits. |
+ return IsValidSlot(heap, chunk, slot) ? KEEP_SLOT : REMOVE_SLOT; |
+ }, |
+ SlotSet::PREFREE_EMPTY_BUCKETS); |
+ } |
} |
} |
template <PointerDirection direction> |
-void RememberedSet<direction>::ClearInvalidTypedSlots(Heap* heap, |
- MemoryChunk* chunk) { |
- STATIC_ASSERT(direction == OLD_TO_NEW); |
- DCHECK(chunk->owner()->identity() == CODE_SPACE); |
- TypedSlotSet* slots = GetTypedSlotSet(chunk); |
- if (slots != nullptr) { |
- slots->Iterate( |
- [heap, chunk](SlotType type, Address host_addr, Address addr) { |
- if (Marking::IsBlack(ObjectMarking::MarkBitFrom(host_addr))) { |
- return KEEP_SLOT; |
- } else { |
- return REMOVE_SLOT; |
- } |
- }, |
- TypedSlotSet::KEEP_EMPTY_CHUNKS); |
- } |
+void RememberedSet<direction>::VerifyValidSlots(Heap* heap) { |
+ Iterate(heap, [heap](Address addr) { |
+ HeapObject* obj = |
+ heap->mark_compact_collector()->FindBlackObjectBySlotSlow(addr); |
+ if (obj == nullptr) { |
+ // The slot is in dead object. |
+ MemoryChunk* chunk = MemoryChunk::FromAnyPointerAddress(heap, addr); |
+ AllocationSpace owner = chunk->owner()->identity(); |
+ // The old to old remembered set should not have dead slots. |
+ CHECK_NE(direction, OLD_TO_OLD); |
+ // The old to new remembered set is allowed to have slots in dead |
+ // objects only in map and large object space because these space |
+ // cannot have raw untagged pointers. |
+ CHECK(owner == MAP_SPACE || owner == LO_SPACE); |
+ } else { |
+ int offset = static_cast<int>(addr - obj->address()); |
+ CHECK(obj->IsValidSlot(offset)); |
+ } |
+ return KEEP_SLOT; |
+ }); |
} |
template <PointerDirection direction> |
bool RememberedSet<direction>::IsValidSlot(Heap* heap, MemoryChunk* chunk, |
Object** slot) { |
STATIC_ASSERT(direction == OLD_TO_NEW); |
+ Object* object = *slot; |
+ if (!heap->InNewSpace(object)) { |
+ return false; |
+ } |
+ HeapObject* heap_object = HeapObject::cast(object); |
// If the target object is not black, the source slot must be part |
// of a non-black (dead) object. |
- return heap->mark_compact_collector()->IsSlotInBlackObject( |
- chunk, reinterpret_cast<Address>(slot)); |
+ return Marking::IsBlack(ObjectMarking::MarkBitFrom(heap_object)) && |
+ heap->mark_compact_collector()->IsSlotInBlackObject( |
+ chunk, reinterpret_cast<Address>(slot)); |
} |
-template void RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(Heap* heap, |
- MemoryChunk* chunk); |
-template void RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots( |
- Heap* heap, MemoryChunk* chunk); |
+template void RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(Heap* heap); |
+template void RememberedSet<OLD_TO_NEW>::VerifyValidSlots(Heap* heap); |
+template void RememberedSet<OLD_TO_OLD>::VerifyValidSlots(Heap* heap); |
} // namespace internal |
} // namespace v8 |