Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index 44262e42b162b58974cf7b2092ea141047856d2a..8539596a62e5cfbd8f4c8850f929ade5e31f1d96 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -314,6 +314,14 @@ void MarkCompactCollector::CollectGarbage() { |
} |
#endif |
+ heap_->store_buffer()->ClearInvalidStoreBufferEntries(); |
+ |
+#ifdef VERIFY_HEAP |
+ if (FLAG_verify_heap) { |
+ heap_->store_buffer()->VerifyValidStoreBufferEntries(); |
+ } |
+#endif |
+ |
SweepSpaces(); |
#ifdef VERIFY_HEAP |
@@ -3048,6 +3056,137 @@ bool MarkCompactCollector::TryPromoteObject(HeapObject* object, |
} |
+bool MarkCompactCollector::IsSlotInBlackObject(Page* p, Address slot) { |
+ // This function does not support large objects right now. |
+ if (p->owner() == NULL) return true; |
+ |
+ uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); |
+ unsigned int start_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; |
+ MarkBit::CellType index_in_cell = 1U |
+ << (mark_bit_index & Bitmap::kBitIndexMask); |
+ MarkBit::CellType* cells = p->markbits()->cells(); |
+ Address cell_base = p->area_start(); |
+ unsigned int cell_base_start_index = Bitmap::IndexToCell( |
+ Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(cell_base))); |
+ |
+ // First check if the object is in the current cell. |
+ MarkBit::CellType slot_mask; |
+ if ((cells[start_index] == 0) || |
+ (base::bits::CountTrailingZeros32(cells[start_index]) > |
+ base::bits::CountTrailingZeros32(cells[start_index] | index_in_cell))) { |
+ // If we are already in the first cell, there is no live object. |
+ if (start_index == cell_base_start_index) return false; |
+ |
+ // If not, find a cell in a preceding cell slot that has a mark bit set. |
+ do { |
+ start_index--; |
+ } while (start_index > cell_base_start_index && cells[start_index] == 0); |
+ |
+ // The slot must be in a dead object if there are no preceding cells that |
+ // have mark bits set. |
+ if (cells[start_index] == 0) { |
+ return false; |
+ } |
+ |
+ // The object is in a preceding cell. Set the mask to find any object. |
+ slot_mask = 0xffffffff; |
+ } else { |
+ // We are interested in object mark bits right before the slot. |
+ slot_mask = index_in_cell - 1; |
+ } |
+ |
+ MarkBit::CellType current_cell = cells[start_index]; |
+ DCHECK(current_cell != 0); |
+ |
+ // Find the last live object in the cell. |
+ unsigned int leading_zeros = |
+ base::bits::CountLeadingZeros32(current_cell & slot_mask); |
+ DCHECK(leading_zeros != 32); |
+ unsigned int offset = Bitmap::kBitIndexMask - leading_zeros; |
+ |
+ cell_base += (start_index - cell_base_start_index) * 32 * kPointerSize; |
+ Address address = cell_base + offset * kPointerSize; |
+ HeapObject* object = HeapObject::FromAddress(address); |
+ DCHECK(object->address() < reinterpret_cast<Address>(slot)); |
+ if (object->address() <= 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. |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) { |
+ // This function does not support large objects right now. |
+ if (p->owner() == NULL) return true; |
+ |
+ for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
+ Address cell_base = it.CurrentCellBase(); |
+ MarkBit::CellType* cell = it.CurrentCell(); |
+ |
+ MarkBit::CellType current_cell = *cell; |
+ if (current_cell == 0) continue; |
+ |
+ int offset = 0; |
+ while (current_cell != 0) { |
+ int trailing_zeros = base::bits::CountTrailingZeros32(current_cell); |
+ current_cell >>= trailing_zeros; |
+ offset += trailing_zeros; |
+ Address address = cell_base + offset * kPointerSize; |
+ |
+ HeapObject* object = HeapObject::FromAddress(address); |
+ int size = object->Size(); |
+ |
+ if (object->address() > slot) return false; |
+ if (object->address() <= slot && slot < (object->address() + size)) { |
+ return true; |
+ } |
+ |
+ offset++; |
+ current_cell >>= 1; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
+bool MarkCompactCollector::IsSlotInLiveObject(HeapObject** address, |
+ HeapObject* object) { |
+ // If the target object is not black, the source slot must be part |
+ // of a non-black (dead) object. |
+ if (!Marking::IsBlack(Marking::MarkBitFrom(object))) { |
+ return false; |
+ } |
+ |
+ // The target object is black but we don't know if the source slot is black. |
+ // The source object could have died and the slot could be part of a free |
+ // space. Find out based on mark bits if the slot is part of a live object. |
+ if (!IsSlotInBlackObject( |
+ Page::FromAddress(reinterpret_cast<Address>(address)), |
+ reinterpret_cast<Address>(address))) { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
+void MarkCompactCollector::VerifyIsSlotInLiveObject(HeapObject** address, |
+ HeapObject* object) { |
+ // The target object has to be black. |
+ CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
+ |
+ // The target object is black but we don't know if the source slot is black. |
+ // The source object could have died and the slot could be part of a free |
+ // space. Use the mark bit iterator to find out about liveness of the slot. |
+ CHECK(IsSlotInBlackObjectSlow( |
+ Page::FromAddress(reinterpret_cast<Address>(address)), |
+ reinterpret_cast<Address>(address))); |
+} |
+ |
+ |
void MarkCompactCollector::EvacuateNewSpace() { |
// There are soft limits in the allocation code, designed trigger a mark |
// sweep collection by failing allocations. But since we are already in |