| Index: src/heap/mark-compact.cc
|
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
| index 5be69a10d1fcddc6cfba672954111ef8d672784c..69d783417e0cf6db53035bc975803ccaa267fe9d 100644
|
| --- a/src/heap/mark-compact.cc
|
| +++ b/src/heap/mark-compact.cc
|
| @@ -2872,128 +2872,6 @@ static String* UpdateReferenceInExternalStringTableEntry(Heap* heap,
|
| return String::cast(*p);
|
| }
|
|
|
| -bool MarkCompactCollector::IsSlotInBlackObject(MemoryChunk* p, Address slot) {
|
| - Space* owner = p->owner();
|
| - DCHECK(owner != heap_->lo_space() && owner != nullptr);
|
| - USE(owner);
|
| -
|
| - // We may be part of a black area.
|
| - if (Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(slot))) {
|
| - return true;
|
| - }
|
| -
|
| - uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot);
|
| - unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2;
|
| - MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index);
|
| - MarkBit::CellType* cells = p->markbits()->cells();
|
| - Address base_address = p->area_start();
|
| - unsigned int base_address_cell_index = Bitmap::IndexToCell(
|
| - Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address)));
|
| -
|
| - // Check if the slot points to the start of an object. This can happen e.g.
|
| - // when we left trim a fixed array. Such slots are invalid and we can remove
|
| - // them.
|
| - if (index_mask > 1) {
|
| - if ((cells[cell_index] & index_mask) != 0 &&
|
| - (cells[cell_index] & (index_mask >> 1)) == 0) {
|
| - return false;
|
| - }
|
| - } else {
|
| - // Left trimming moves the mark bits so we cannot be in the very first cell.
|
| - DCHECK(cell_index != base_address_cell_index);
|
| - if ((cells[cell_index] & index_mask) != 0 &&
|
| - (cells[cell_index - 1] & (1u << Bitmap::kBitIndexMask)) == 0) {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // Check if the object is in the current cell.
|
| - MarkBit::CellType slot_mask;
|
| - if ((cells[cell_index] == 0) ||
|
| - (base::bits::CountTrailingZeros32(cells[cell_index]) >
|
| - base::bits::CountTrailingZeros32(cells[cell_index] | index_mask))) {
|
| - // If we are already in the first cell, there is no live object.
|
| - if (cell_index == base_address_cell_index) return false;
|
| -
|
| - // If not, find a cell in a preceding cell slot that has a mark bit set.
|
| - do {
|
| - cell_index--;
|
| - } while (cell_index > base_address_cell_index && cells[cell_index] == 0);
|
| -
|
| - // The slot must be in a dead object if there are no preceding cells that
|
| - // have mark bits set.
|
| - if (cells[cell_index] == 0) {
|
| - return false;
|
| - }
|
| -
|
| - // The object is in a preceding cell. Set the mask to find any object.
|
| - slot_mask = ~0u;
|
| - } else {
|
| - // We are interested in object mark bits right before the slot.
|
| - slot_mask = index_mask + (index_mask - 1);
|
| - }
|
| -
|
| - MarkBit::CellType current_cell = cells[cell_index];
|
| - CHECK(current_cell != 0);
|
| -
|
| - // Find the last live object in the cell.
|
| - unsigned int leading_zeros =
|
| - base::bits::CountLeadingZeros32(current_cell & slot_mask);
|
| - CHECK(leading_zeros != Bitmap::kBitsPerCell);
|
| - int offset = static_cast<int>(Bitmap::kBitIndexMask - leading_zeros) - 1;
|
| -
|
| - base_address += (cell_index - base_address_cell_index) *
|
| - Bitmap::kBitsPerCell * kPointerSize;
|
| - Address address = base_address + offset * kPointerSize;
|
| -
|
| - // If the found mark bit is part of a black area, the slot cannot be part
|
| - // of a live object since it is not marked.
|
| - if (p->IsBlackAreaEndMarker(address + kPointerSize)) return false;
|
| -
|
| - HeapObject* object = HeapObject::FromAddress(address);
|
| - CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
| - CHECK(object->address() < reinterpret_cast<Address>(slot));
|
| - if ((object->address() + kPointerSize) <= slot &&
|
| - (object->address() + object->Size()) > slot) {
|
| - // If the slot is within the last found object in the cell, the slot is
|
| - // in a live object.
|
| - // Slots pointing to the first word of an object are invalid and removed.
|
| - // This can happen when we move the object header while left trimming.
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) {
|
| - Page* p = Page::FromAddress(slot);
|
| - Space* owner = p->owner();
|
| - if (owner == heap_->lo_space() || owner == nullptr) {
|
| - Object* large_object = heap_->lo_space()->FindObject(slot);
|
| - // This object has to exist, otherwise we would not have recorded a slot
|
| - // for it.
|
| - CHECK(large_object->IsHeapObject());
|
| - HeapObject* large_heap_object = HeapObject::cast(large_object);
|
| -
|
| - if (IsMarked(large_heap_object)) {
|
| - return large_heap_object;
|
| - }
|
| - return nullptr;
|
| - }
|
| -
|
| - LiveObjectIterator<kBlackObjects> it(p);
|
| - HeapObject* object = nullptr;
|
| - while ((object = it.Next()) != nullptr) {
|
| - int size = object->Size();
|
| - if (object->address() > slot) return nullptr;
|
| - if (object->address() <= slot && slot < (object->address() + size)) {
|
| - return object;
|
| - }
|
| - }
|
| -
|
| - return nullptr;
|
| -}
|
| -
|
| -
|
| void MarkCompactCollector::EvacuateNewSpacePrologue() {
|
| NewSpace* new_space = heap()->new_space();
|
| // Append the list of new space pages to be processed.
|
| @@ -3316,23 +3194,38 @@ class EvacuationWeakObjectRetainer : public WeakObjectRetainer {
|
| }
|
| };
|
|
|
| +MarkCompactCollector::Sweeper::ClearOldToNewSlotsMode
|
| +MarkCompactCollector::Sweeper::GetClearOldToNewSlotsMode(Page* p) {
|
| + AllocationSpace identity = p->owner()->identity();
|
| + if (p->old_to_new_slots() &&
|
| + (identity == OLD_SPACE || identity == MAP_SPACE)) {
|
| + return MarkCompactCollector::Sweeper::CLEAR_REGULAR_SLOTS;
|
| + } else if (p->typed_old_to_new_slots() && identity == CODE_SPACE) {
|
| + return MarkCompactCollector::Sweeper::CLEAR_TYPED_SLOTS;
|
| + }
|
| + return MarkCompactCollector::Sweeper::DO_NOT_CLEAR;
|
| +}
|
| +
|
| 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 || identity == OLD_SPACE ||
|
| - identity == CODE_SPACE || identity == MAP_SPACE);
|
| + DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE ||
|
| + space->identity() == CODE_SPACE || space->identity() == MAP_SPACE);
|
| DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone());
|
|
|
| + // If there are old-to-new slots in that page, we have to filter out slots
|
| + // that are in dead memory which is freed by the sweeper.
|
| + ClearOldToNewSlotsMode slots_clearing_mode = GetClearOldToNewSlotsMode(p);
|
| +
|
| + // The free ranges map is used for filtering typed slots.
|
| + std::map<uint32_t, uint32_t> free_ranges;
|
| +
|
| // Before we sweep objects on the page, we free dead array buffers which
|
| // requires valid mark bits.
|
| ArrayBufferTracker::FreeDead(p);
|
|
|
| - // We also release the black area markers here.
|
| - p->ReleaseBlackAreaEndMarkerMap();
|
| -
|
| Address free_start = p->area_start();
|
| DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
|
|
|
| @@ -3352,8 +3245,7 @@ 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();
|
| @@ -3372,9 +3264,13 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| ClearRecordedSlots::kNo);
|
| }
|
|
|
| - if (clear_slots) {
|
| + if (slots_clearing_mode == CLEAR_REGULAR_SLOTS) {
|
| RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, free_end,
|
| SlotSet::KEEP_EMPTY_BUCKETS);
|
| + } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) {
|
| + free_ranges.insert(std::pair<uint32_t, uint32_t>(
|
| + static_cast<uint32_t>(free_start - p->address()),
|
| + static_cast<uint32_t>(free_end - p->address())));
|
| }
|
| }
|
| Map* map = object->synchronized_map();
|
| @@ -3406,12 +3302,21 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
| ClearRecordedSlots::kNo);
|
| }
|
|
|
| - if (clear_slots) {
|
| + if (slots_clearing_mode == CLEAR_REGULAR_SLOTS) {
|
| RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(),
|
| SlotSet::KEEP_EMPTY_BUCKETS);
|
| + } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) {
|
| + free_ranges.insert(std::pair<uint32_t, uint32_t>(
|
| + static_cast<uint32_t>(free_start - p->address()),
|
| + static_cast<uint32_t>(p->area_end() - p->address())));
|
| }
|
| }
|
|
|
| + // Clear invalid typed slots after collection all free ranges.
|
| + if (slots_clearing_mode == CLEAR_TYPED_SLOTS) {
|
| + p->typed_old_to_new_slots()->RemoveInvaldSlots(free_ranges);
|
| + }
|
| +
|
| // Clear the mark bits of that page and reset live bytes count.
|
| p->ClearLiveness();
|
|
|
| @@ -3837,9 +3742,6 @@ int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page,
|
| if (identity == NEW_SPACE) {
|
| RawSweep(page, IGNORE_FREE_LIST, free_space_mode);
|
| } else {
|
| - if (identity == CODE_SPACE) {
|
| - RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots(heap_, page);
|
| - }
|
| max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode);
|
| }
|
|
|
| @@ -3907,7 +3809,6 @@ void MarkCompactCollector::StartSweepSpace(PagedSpace* space) {
|
| if (p->IsEvacuationCandidate()) {
|
| // Will be processed in EvacuateNewSpaceAndCandidates.
|
| DCHECK(evacuation_candidates_.length() > 0);
|
| - DCHECK(!p->HasBlackAreas());
|
| continue;
|
| }
|
|
|
|
|