Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index c231623d52a16243bacdfe9b617916009ab0efe2..e24e345fb57b31bfb4e47680d9092b70ca09846c 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -4723,35 +4723,12 @@ void Heap::ZapFromSpace() { |
} |
} |
-void Heap::IteratePromotedObjectPointers(HeapObject* object, Address start, |
- Address end, bool record_slots, |
- ObjectSlotCallback callback) { |
- Address slot_address = start; |
- Page* page = Page::FromAddress(start); |
- |
- while (slot_address < end) { |
- Object** slot = reinterpret_cast<Object**>(slot_address); |
- Object* target = *slot; |
- if (target->IsHeapObject()) { |
- if (Heap::InFromSpace(target)) { |
- callback(reinterpret_cast<HeapObject**>(slot), |
- HeapObject::cast(target)); |
- Object* new_target = *slot; |
- if (InNewSpace(new_target)) { |
- SLOW_DCHECK(Heap::InToSpace(new_target)); |
- SLOW_DCHECK(new_target->IsHeapObject()); |
- RememberedSet<OLD_TO_NEW>::Insert(page, slot_address); |
- } |
- SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); |
- } else if (record_slots && |
- MarkCompactCollector::IsOnEvacuationCandidate(target)) { |
- mark_compact_collector()->RecordSlot(object, slot, target); |
- } |
- } |
- slot_address += kPointerSize; |
- } |
-} |
+enum IteratePromotedObjectsMode { |
+ RECORD_ONLY, |
+ RECORD_AND_SCAVENGE, |
+}; |
+template <IteratePromotedObjectsMode mode> |
class IteratePromotedObjectsVisitor final : public ObjectVisitor { |
public: |
IteratePromotedObjectsVisitor(Heap* heap, HeapObject* target, |
@@ -4761,13 +4738,36 @@ class IteratePromotedObjectsVisitor final : public ObjectVisitor { |
record_slots_(record_slots), |
callback_(callback) {} |
- V8_INLINE void VisitPointers(Object** start, Object** end) override { |
- heap_->IteratePromotedObjectPointers( |
- target_, reinterpret_cast<Address>(start), |
- reinterpret_cast<Address>(end), record_slots_, callback_); |
+ inline void VisitPointers(Object** start, Object** end) override { |
+ Address slot_address = reinterpret_cast<Address>(start); |
+ Page* page = Page::FromAddress(slot_address); |
+ |
+ while (slot_address < reinterpret_cast<Address>(end)) { |
+ Object** slot = reinterpret_cast<Object**>(slot_address); |
+ Object* target = *slot; |
+ |
+ if (mode == RECORD_AND_SCAVENGE && heap_->InNewSpace(target)) { |
+ callback_(reinterpret_cast<HeapObject**>(slot), |
+ HeapObject::cast(target)); |
+ target = *slot; |
+ DCHECK(target->IsHeapObject); |
+ SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(target)); |
+ } |
+ |
+ if (heap_->InNewSpace(target)) { |
+ SLOW_DCHECK(Heap::InToSpace(new_target)); |
+ SLOW_DCHECK(new_target->IsHeapObject()); |
+ RememberedSet<OLD_TO_NEW>::Insert(page, slot_address); |
+ } else if (record_slots_ && |
+ MarkCompactCollector::IsOnEvacuationCandidate(target)) { |
+ heap_->mark_compact_collector()->RecordSlot(target_, slot, target); |
+ } |
+ |
+ slot_address += kPointerSize; |
+ } |
} |
- V8_INLINE void VisitCodeEntry(Address code_entry_slot) override { |
+ inline void VisitCodeEntry(Address code_entry_slot) override { |
// Black allocation requires us to process objects referenced by |
// promoted objects. |
if (heap_->incremental_marking()->black_allocation()) { |
@@ -4798,8 +4798,21 @@ void Heap::IteratePromotedObject(HeapObject* target, int size, |
record_slots = Marking::IsBlack(mark_bit); |
} |
- IteratePromotedObjectsVisitor visitor(this, target, record_slots, callback); |
- target->IterateBody(target->map()->instance_type(), size, &visitor); |
+ IteratePromotedObjectsVisitor<RECORD_AND_SCAVENGE> |
+ record_and_scavenge_visitor(this, target, record_slots, callback); |
+ if (target->IsJSFunction()) { |
+ // JSFunctions reachable through kNextFunctionLinkOffset are weak and should |
+ // only trigger recording, not a scavenge. |
+ JSFunction::BodyDescriptorWeakCode::IterateBody( |
+ target, size, &record_and_scavenge_visitor); |
+ IteratePromotedObjectsVisitor<RECORD_ONLY> record_only_visitor( |
+ this, target, record_slots, callback); |
+ JSFunction::BodyDescriptorWeakFields::IterateBody(target, size, |
+ &record_only_visitor); |
+ } else { |
+ target->IterateBody(target->map()->instance_type(), size, |
+ &record_and_scavenge_visitor); |
+ } |
// When black allocations is on, we have to visit not already marked black |
// objects (in new space) promoted to black pages to keep their references |