[heap] Clear markbits for evacuated objects in ReRecordPage
Move clearing of markbits in the evacuated area into ReRecordPage, which also resets all other metadata for that memory area. Since this case is now handled in ReRecordPage, all other use cases can delete markbits for the whole chunk and allows the VisitBlackObjects* methods to not deal with markbits anymore. Bug: chromium:1359294, v8:12578 Change-Id: Ic98debe04efb7f415cf06efb58af0f728071aa65 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3879499 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Dominik Inführ <dinfuehr@chromium.org> Cr-Commit-Position: refs/heads/main@{#83072}
This commit is contained in:
parent
2a8f562877
commit
682947f813
@ -4331,22 +4331,20 @@ void FullEvacuator::RawEvacuatePage(MemoryChunk* chunk, intptr_t* live_bytes) {
|
||||
#if DEBUG
|
||||
new_space_visitor_.DisableAbortEvacuationAtAddress(chunk);
|
||||
#endif // DEBUG
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(
|
||||
chunk, marking_state, &new_space_visitor_,
|
||||
LiveObjectVisitor::kClearMarkbits);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(chunk, marking_state,
|
||||
&new_space_visitor_);
|
||||
marking_state->ClearLiveness(chunk);
|
||||
break;
|
||||
case kPageNewToOld:
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(
|
||||
chunk, marking_state, &new_to_old_page_visitor_,
|
||||
LiveObjectVisitor::kKeepMarking);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(chunk, marking_state,
|
||||
&new_to_old_page_visitor_);
|
||||
new_to_old_page_visitor_.account_moved_bytes(
|
||||
marking_state->live_bytes(chunk));
|
||||
break;
|
||||
case kPageNewToNew:
|
||||
DCHECK(!v8_flags.minor_mc);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(
|
||||
chunk, marking_state, &new_to_new_page_visitor_,
|
||||
LiveObjectVisitor::kKeepMarking);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(chunk, marking_state,
|
||||
&new_to_new_page_visitor_);
|
||||
new_to_new_page_visitor_.account_moved_bytes(
|
||||
marking_state->live_bytes(chunk));
|
||||
break;
|
||||
@ -4358,9 +4356,10 @@ void FullEvacuator::RawEvacuatePage(MemoryChunk* chunk, intptr_t* live_bytes) {
|
||||
old_space_visitor_.SetUpAbortEvacuationAtAddress(chunk);
|
||||
#endif // DEBUG
|
||||
const bool success = LiveObjectVisitor::VisitBlackObjects(
|
||||
chunk, marking_state, &old_space_visitor_,
|
||||
LiveObjectVisitor::kClearMarkbits, &failed_object);
|
||||
if (!success) {
|
||||
chunk, marking_state, &old_space_visitor_, &failed_object);
|
||||
if (success) {
|
||||
marking_state->ClearLiveness(chunk);
|
||||
} else {
|
||||
if (v8_flags.crash_on_aborted_evacuation) {
|
||||
heap_->FatalProcessOutOfMemory("FullEvacuator::RawEvacuatePage");
|
||||
} else {
|
||||
@ -4611,15 +4610,13 @@ class EvacuationWeakObjectRetainer : public WeakObjectRetainer {
|
||||
void MarkCompactCollector::RecordLiveSlotsOnPage(Page* page) {
|
||||
EvacuateRecordOnlyVisitor visitor(heap());
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(page, non_atomic_marking_state(),
|
||||
&visitor,
|
||||
LiveObjectVisitor::kKeepMarking);
|
||||
&visitor);
|
||||
}
|
||||
|
||||
template <class Visitor, typename MarkingState>
|
||||
bool LiveObjectVisitor::VisitBlackObjects(MemoryChunk* chunk,
|
||||
MarkingState* marking_state,
|
||||
Visitor* visitor,
|
||||
IterationMode iteration_mode,
|
||||
HeapObject* failed_object) {
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"),
|
||||
"LiveObjectVisitor::VisitBlackObjects");
|
||||
@ -4627,26 +4624,17 @@ bool LiveObjectVisitor::VisitBlackObjects(MemoryChunk* chunk,
|
||||
LiveObjectRange<kBlackObjects>(chunk, marking_state->bitmap(chunk))) {
|
||||
HeapObject const object = object_and_size.first;
|
||||
if (!visitor->Visit(object, object_and_size.second)) {
|
||||
if (iteration_mode == kClearMarkbits) {
|
||||
marking_state->bitmap(chunk)->ClearRange(
|
||||
chunk->AddressToMarkbitIndex(chunk->area_start()),
|
||||
chunk->AddressToMarkbitIndex(object.address()));
|
||||
*failed_object = object;
|
||||
}
|
||||
*failed_object = object;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (iteration_mode == kClearMarkbits) {
|
||||
marking_state->ClearLiveness(chunk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Visitor, typename MarkingState>
|
||||
void LiveObjectVisitor::VisitBlackObjectsNoFail(MemoryChunk* chunk,
|
||||
MarkingState* marking_state,
|
||||
Visitor* visitor,
|
||||
IterationMode iteration_mode) {
|
||||
Visitor* visitor) {
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"),
|
||||
"LiveObjectVisitor::VisitBlackObjectsNoFail");
|
||||
if (chunk->IsLargePage()) {
|
||||
@ -4666,9 +4654,6 @@ void LiveObjectVisitor::VisitBlackObjectsNoFail(MemoryChunk* chunk,
|
||||
DCHECK(success);
|
||||
}
|
||||
}
|
||||
if (iteration_mode == kClearMarkbits) {
|
||||
marking_state->ClearLiveness(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MarkingState>
|
||||
@ -5422,6 +5407,11 @@ void ReRecordPage(Heap* heap,
|
||||
// Aborted compaction page. We have to record slots here, since we
|
||||
// might not have recorded them in first place.
|
||||
|
||||
// Remove mark bits in evacuated area.
|
||||
marking_state->bitmap(page)->ClearRange(
|
||||
page->AddressToMarkbitIndex(page->area_start()),
|
||||
page->AddressToMarkbitIndex(failed_start));
|
||||
|
||||
// Remove outdated slots.
|
||||
RememberedSet<OLD_TO_NEW>::RemoveRange(page, page->address(), failed_start,
|
||||
SlotSet::FREE_EMPTY_BUCKETS);
|
||||
@ -5448,8 +5438,8 @@ void ReRecordPage(Heap* heap,
|
||||
LiveObjectVisitor::RecomputeLiveBytes(page, marking_state);
|
||||
// Re-record slots.
|
||||
EvacuateRecordOnlyVisitor record_visitor(heap);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(
|
||||
page, marking_state, &record_visitor, LiveObjectVisitor::kKeepMarking);
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(page, marking_state,
|
||||
&record_visitor);
|
||||
// Array buffers will be processed during pointer updating.
|
||||
}
|
||||
|
||||
@ -6646,8 +6636,7 @@ void YoungGenerationEvacuator::RawEvacuatePage(MemoryChunk* chunk,
|
||||
*live_bytes = marking_state->live_bytes(chunk);
|
||||
DCHECK_EQ(kPageNewToOld, ComputeEvacuationMode(chunk));
|
||||
LiveObjectVisitor::VisitBlackObjectsNoFail(chunk, marking_state,
|
||||
&new_to_old_page_visitor_,
|
||||
LiveObjectVisitor::kKeepMarking);
|
||||
&new_to_old_page_visitor_);
|
||||
new_to_old_page_visitor_.account_moved_bytes(
|
||||
marking_state->live_bytes(chunk));
|
||||
if (!chunk->IsLargePage()) {
|
||||
|
@ -156,25 +156,17 @@ class LiveObjectRange {
|
||||
|
||||
class LiveObjectVisitor : AllStatic {
|
||||
public:
|
||||
enum IterationMode {
|
||||
kKeepMarking,
|
||||
kClearMarkbits,
|
||||
};
|
||||
|
||||
// Visits black objects on a MemoryChunk until the Visitor returns |false| for
|
||||
// an object. If IterationMode::kClearMarkbits is passed the markbits and
|
||||
// slots for visited objects are cleared for each successfully visited object.
|
||||
// an object.
|
||||
template <class Visitor, typename MarkingState>
|
||||
static bool VisitBlackObjects(MemoryChunk* chunk, MarkingState* state,
|
||||
Visitor* visitor, IterationMode iteration_mode,
|
||||
HeapObject* failed_object);
|
||||
Visitor* visitor, HeapObject* failed_object);
|
||||
|
||||
// Visits black objects on a MemoryChunk. The visitor is not allowed to fail
|
||||
// visitation for an object.
|
||||
template <class Visitor, typename MarkingState>
|
||||
static void VisitBlackObjectsNoFail(MemoryChunk* chunk, MarkingState* state,
|
||||
Visitor* visitor,
|
||||
IterationMode iteration_mode);
|
||||
Visitor* visitor);
|
||||
|
||||
template <typename MarkingState>
|
||||
static void RecomputeLiveBytes(MemoryChunk* chunk, MarkingState* state);
|
||||
|
Loading…
Reference in New Issue
Block a user