| Index: src/heap/mark-compact.cc
|
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
| index da5fe3501a05353143db03a1ccd2b433368f0631..93baeca4af1bfc547382f16bca2bdf12a5f06bd6 100644
|
| --- a/src/heap/mark-compact.cc
|
| +++ b/src/heap/mark-compact.cc
|
| @@ -3320,9 +3320,10 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| Page* p, FreeListRebuildingMode free_list_mode,
|
| FreeSpaceTreatmentMode free_space_mode) {
|
| Space* space = p->owner();
|
| + AllocationSpace identity = space->identity();
|
| DCHECK_NOT_NULL(space);
|
| - DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE ||
|
| - space->identity() == CODE_SPACE || space->identity() == MAP_SPACE);
|
| + DCHECK(free_list_mode == IGNORE_FREE_LIST || identity == OLD_SPACE ||
|
| + identity == CODE_SPACE || identity == MAP_SPACE);
|
| DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone());
|
|
|
| // Before we sweep objects on the page, we free dead array buffers which
|
| @@ -3351,6 +3352,8 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
|
|
| LiveObjectIterator<kBlackObjects> it(p);
|
| HeapObject* object = NULL;
|
| + bool clear_slots =
|
| + p->old_to_new_slots() && (identity == OLD_SPACE || identity == MAP_SPACE);
|
| while ((object = it.Next()) != NULL) {
|
| DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
| Address free_end = object->address();
|
| @@ -3368,6 +3371,11 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size),
|
| ClearRecordedSlots::kNo);
|
| }
|
| +
|
| + if (clear_slots) {
|
| + RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, free_end,
|
| + SlotSet::KEEP_EMPTY_BUCKETS);
|
| + }
|
| }
|
| Map* map = object->synchronized_map();
|
| int size = object->SizeFromMap(map);
|
| @@ -3383,9 +3391,6 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| free_start = free_end + size;
|
| }
|
|
|
| - // Clear the mark bits of that page and reset live bytes count.
|
| - p->ClearLiveness();
|
| -
|
| if (free_start != p->area_end()) {
|
| CHECK_GT(p->area_end(), free_start);
|
| size_t size = static_cast<size_t>(p->area_end() - free_start);
|
| @@ -3400,7 +3405,16 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size),
|
| ClearRecordedSlots::kNo);
|
| }
|
| +
|
| + if (clear_slots) {
|
| + RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(),
|
| + SlotSet::KEEP_EMPTY_BUCKETS);
|
| + }
|
| }
|
| +
|
| + // Clear the mark bits of that page and reset live bytes count.
|
| + p->ClearLiveness();
|
| +
|
| p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
|
| if (free_list_mode == IGNORE_FREE_LIST) return 0;
|
| return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
|
| @@ -3615,6 +3629,11 @@ class PointerUpdateJobTraits {
|
|
|
| static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap,
|
| Address slot_address) {
|
| + // There may be concurrent action on slots in dead objects. Concurrent
|
| + // sweeper threads may overwrite the slot content with a free space object.
|
| + // Moreover, the pointed-to object may also get concurrently overwritten
|
| + // with a free space object. The sweeper always gets priority performing
|
| + // these writes.
|
| base::NoBarrierAtomicValue<Object*>* slot =
|
| base::NoBarrierAtomicValue<Object*>::FromAddress(slot_address);
|
| Object* slot_reference = slot->Value();
|
| @@ -3630,8 +3649,10 @@ class PointerUpdateJobTraits {
|
| if (map_word.ToRawValue() < Page::kPageSize) {
|
| return REMOVE_SLOT;
|
| }
|
| - // Update the corresponding slot.
|
| - slot->SetValue(map_word.ToForwardingAddress());
|
| + // Update the corresponding slot only if the slot content did not
|
| + // change in the meantime. This may happen when a concurrent sweeper
|
| + // thread stored a free space object at that memory location.
|
| + slot->TrySetValue(slot_reference, map_word.ToForwardingAddress());
|
| }
|
| // If the object was in from space before and is after executing the
|
| // callback in to space, the object is still live.
|
| @@ -3816,9 +3837,7 @@ int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page,
|
| if (identity == NEW_SPACE) {
|
| RawSweep(page, IGNORE_FREE_LIST, free_space_mode);
|
| } else {
|
| - if (identity == OLD_SPACE || identity == MAP_SPACE) {
|
| - RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(heap_, page);
|
| - } else {
|
| + if (identity == CODE_SPACE) {
|
| RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots(heap_, page);
|
| }
|
| max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode);
|
|
|