Remove lazy sweeping of new space and corresponding complicated pointer updating logic.

We can do that now since we have the invariant that the store buffer always has valid slots after marking.

BUG=

Review URL: https://codereview.chromium.org/991853002

Cr-Commit-Position: refs/heads/master@{#27105}
This commit is contained in:
hpayer 2015-03-10 06:42:15 -07:00 committed by Commit bot
parent 0fd9bf8f14
commit 02ce445394
4 changed files with 25 additions and 68 deletions

View File

@ -3008,19 +3008,15 @@ void PointersUpdatingVisitor::CheckLayoutDescriptorAndDie(Heap* heap,
static void UpdatePointer(HeapObject** address, HeapObject* object) {
Address new_addr = Memory::Address_at(object->address());
// The new space sweep will overwrite the map word of dead objects
// with NULL. In this case we do not need to transfer this entry to
// the store buffer which we are rebuilding.
// We perform the pointer update with a no barrier compare-and-swap. The
// compare and swap may fail in the case where the pointer update tries to
// update garbage memory which was concurrently accessed by the sweeper.
if (new_addr != NULL) {
base::NoBarrier_CompareAndSwap(
reinterpret_cast<base::AtomicWord*>(address),
reinterpret_cast<base::AtomicWord>(object),
reinterpret_cast<base::AtomicWord>(HeapObject::FromAddress(new_addr)));
MapWord map_word = object->map_word();
// The store buffer can still contain stale pointers in dead large objects.
// Ignore these pointers here.
DCHECK(map_word.IsForwardingAddress() ||
object->GetHeap()->lo_space()->FindPage(
reinterpret_cast<Address>(address)) != NULL);
if (map_word.IsForwardingAddress()) {
// Update the corresponding slot.
*address = map_word.ToForwardingAddress();
}
}
@ -3652,8 +3648,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS);
StoreBufferRebuildScope scope(heap_, heap_->store_buffer(),
&Heap::ScavengeStoreBufferCallback);
heap_->store_buffer()->IteratePointersToNewSpaceAndClearMaps(
&UpdatePointer);
heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer);
}
{

View File

@ -49,14 +49,6 @@ void StoreBuffer::EnterDirectlyIntoStoreBuffer(Address addr) {
}
}
}
void StoreBuffer::ClearDeadObject(HeapObject* object) {
Address& map_field = Memory::Address_at(object->address());
if (heap_->map_space()->Contains(map_field)) {
map_field = NULL;
}
}
}
} // namespace v8::internal

View File

@ -379,8 +379,7 @@ void StoreBuffer::GCEpilogue() {
void StoreBuffer::ProcessOldToNewSlot(Address slot_address,
ObjectSlotCallback slot_callback,
bool clear_maps) {
ObjectSlotCallback slot_callback) {
Object** slot = reinterpret_cast<Object**>(slot_address);
Object* object = reinterpret_cast<Object*>(
base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
@ -390,9 +389,6 @@ void StoreBuffer::ProcessOldToNewSlot(Address slot_address,
if (heap_->InFromSpace(object)) {
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
DCHECK(heap_object->IsHeapObject());
// The new space object was not promoted if it still contains a map
// pointer. Clear the map field now lazily (during full GC).
if (clear_maps) ClearDeadObject(heap_object);
slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
object = reinterpret_cast<Object*>(
base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
@ -408,17 +404,16 @@ void StoreBuffer::ProcessOldToNewSlot(Address slot_address,
void StoreBuffer::FindPointersToNewSpaceInRegion(
Address start, Address end, ObjectSlotCallback slot_callback,
bool clear_maps) {
Address start, Address end, ObjectSlotCallback slot_callback) {
for (Address slot_address = start; slot_address < end;
slot_address += kPointerSize) {
ProcessOldToNewSlot(slot_address, slot_callback, clear_maps);
ProcessOldToNewSlot(slot_address, slot_callback);
}
}
void StoreBuffer::IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
bool clear_maps) {
void StoreBuffer::IteratePointersInStoreBuffer(
ObjectSlotCallback slot_callback) {
Address* limit = old_top_;
old_top_ = old_start_;
{
@ -427,7 +422,7 @@ void StoreBuffer::IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
#ifdef DEBUG
Address* saved_top = old_top_;
#endif
ProcessOldToNewSlot(*current, slot_callback, clear_maps);
ProcessOldToNewSlot(*current, slot_callback);
DCHECK(old_top_ == saved_top + 1 || old_top_ == saved_top);
}
}
@ -478,18 +473,6 @@ void StoreBuffer::VerifyValidStoreBufferEntries() {
void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
IteratePointersToNewSpace(slot_callback, false);
}
void StoreBuffer::IteratePointersToNewSpaceAndClearMaps(
ObjectSlotCallback slot_callback) {
IteratePointersToNewSpace(slot_callback, true);
}
void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
bool clear_maps) {
// We do not sort or remove duplicated entries from the store buffer because
// we expect that callback will rebuild the store buffer thus removing
// all duplicates and pointers to old space.
@ -498,7 +481,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
// TODO(gc): we want to skip slots on evacuation candidates
// but we can't simply figure that out from slot address
// because slot can belong to a large object.
IteratePointersInStoreBuffer(slot_callback, clear_maps);
IteratePointersInStoreBuffer(slot_callback);
// We are done scanning all the pointers that were in the store buffer, but
// there may be some pages marked scan_on_scavenge that have pointers to new
@ -527,7 +510,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
DCHECK(array->IsFixedArray());
Address start = array->address();
Address end = start + array->Size();
FindPointersToNewSpaceInRegion(start, end, slot_callback, clear_maps);
FindPointersToNewSpaceInRegion(start, end, slot_callback);
} else {
Page* page = reinterpret_cast<Page*>(chunk);
PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
@ -542,7 +525,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
FindPointersToNewSpaceInRegion(
heap_object->address() + Map::kPointerFieldsBeginOffset,
heap_object->address() + Map::kPointerFieldsEndOffset,
slot_callback, clear_maps);
slot_callback);
}
}
} else {
@ -577,8 +560,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
&end_of_region_offset)) {
FindPointersToNewSpaceInRegion(
obj_address + offset,
obj_address + end_of_region_offset, slot_callback,
clear_maps);
obj_address + end_of_region_offset, slot_callback);
}
offset = end_of_region_offset;
}
@ -588,7 +570,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
Address end_address = obj_address + end_offset;
// Object has only tagged fields.
FindPointersToNewSpaceInRegion(start_address, end_address,
slot_callback, clear_maps);
slot_callback);
#if V8_DOUBLE_FIELDS_UNBOXING
}
#endif

View File

@ -20,8 +20,7 @@ class StoreBuffer;
typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to);
typedef void (StoreBuffer::*RegionCallback)(Address start, Address end,
ObjectSlotCallback slot_callback,
bool clear_maps);
ObjectSlotCallback slot_callback);
// Used to implement the write barrier by collecting addresses of pointers
// between spaces.
@ -60,10 +59,6 @@ class StoreBuffer {
// surviving old-to-new pointers into the store buffer to rebuild it.
void IteratePointersToNewSpace(ObjectSlotCallback callback);
// Same as IteratePointersToNewSpace but additonally clears maps in objects
// referenced from the store buffer that do not contain a forwarding pointer.
void IteratePointersToNewSpaceAndClearMaps(ObjectSlotCallback callback);
static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2);
static const int kStoreBufferSize = kStoreBufferOverflowBit;
static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address);
@ -152,17 +147,11 @@ class StoreBuffer {
void Uniq();
void ExemptPopularPages(int prime_sample_step, int threshold);
// Set the map field of the object to NULL if contains a map.
inline void ClearDeadObject(HeapObject* object);
void ProcessOldToNewSlot(Address slot_address,
ObjectSlotCallback slot_callback, bool clear_maps);
void IteratePointersToNewSpace(ObjectSlotCallback callback, bool clear_maps);
ObjectSlotCallback slot_callback);
void FindPointersToNewSpaceInRegion(Address start, Address end,
ObjectSlotCallback slot_callback,
bool clear_maps);
ObjectSlotCallback slot_callback);
// For each region of pointers on a page in use from an old space call
// visit_pointer_region callback.
@ -173,8 +162,7 @@ class StoreBuffer {
RegionCallback region_callback,
ObjectSlotCallback slot_callback);
void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
bool clear_maps);
void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback);
#ifdef VERIFY_HEAP
void VerifyPointers(LargeObjectSpace* space);