Index: src/store-buffer.cc |
diff --git a/src/store-buffer.cc b/src/store-buffer.cc |
index 0386280de65b0948c22c54638cbba4c0e3646457..9705b60489800feb74d8d09d1a72ca85cf9f0a4b 100644 |
--- a/src/store-buffer.cc |
+++ b/src/store-buffer.cc |
@@ -364,7 +364,8 @@ void StoreBuffer::VerifyPointers(PagedSpace* space, |
reinterpret_cast<PagedSpace*>(page->owner()), |
page, |
region_callback, |
- &DummyScavengePointer); |
+ &DummyScavengePointer, |
+ false); |
} |
} |
@@ -412,7 +413,10 @@ void StoreBuffer::GCEpilogue() { |
void StoreBuffer::FindPointersToNewSpaceInRegion( |
- Address start, Address end, ObjectSlotCallback slot_callback) { |
+ Address start, |
+ Address end, |
+ ObjectSlotCallback slot_callback, |
+ bool clear_maps) { |
for (Address slot_address = start; |
slot_address < end; |
slot_address += kPointerSize) { |
@@ -420,6 +424,9 @@ void StoreBuffer::FindPointersToNewSpaceInRegion( |
if (heap_->InNewSpace(*slot)) { |
HeapObject* object = reinterpret_cast<HeapObject*>(*slot); |
ASSERT(object->IsHeapObject()); |
+ // The new space object was not promoted if it still contains a map |
+ // pointer. Clear the map field now lazily. |
+ if (clear_maps) ClearDeadObject(object); |
slot_callback(reinterpret_cast<HeapObject**>(slot), object); |
if (heap_->InNewSpace(*slot)) { |
EnterDirectlyIntoStoreBuffer(slot_address); |
@@ -446,7 +453,8 @@ static inline Address MapEndAlign(Address addr) { |
void StoreBuffer::FindPointersToNewSpaceInMaps( |
Address start, |
Address end, |
- ObjectSlotCallback slot_callback) { |
+ ObjectSlotCallback slot_callback, |
+ bool clear_maps) { |
ASSERT(MapStartAlign(start) == start); |
ASSERT(MapEndAlign(end) == end); |
@@ -460,7 +468,8 @@ void StoreBuffer::FindPointersToNewSpaceInMaps( |
FindPointersToNewSpaceInRegion(pointer_fields_start, |
pointer_fields_end, |
- slot_callback); |
+ slot_callback, |
+ clear_maps); |
map_address += Map::kSize; |
} |
} |
@@ -469,7 +478,8 @@ void StoreBuffer::FindPointersToNewSpaceInMaps( |
void StoreBuffer::FindPointersToNewSpaceInMapsRegion( |
Address start, |
Address end, |
- ObjectSlotCallback slot_callback) { |
+ ObjectSlotCallback slot_callback, |
+ bool clear_maps) { |
Address map_aligned_start = MapStartAlign(start); |
Address map_aligned_end = MapEndAlign(end); |
@@ -478,7 +488,8 @@ void StoreBuffer::FindPointersToNewSpaceInMapsRegion( |
FindPointersToNewSpaceInMaps(map_aligned_start, |
map_aligned_end, |
- slot_callback); |
+ slot_callback, |
+ clear_maps); |
} |
@@ -500,7 +511,8 @@ void StoreBuffer::FindPointersToNewSpaceOnPage( |
PagedSpace* space, |
Page* page, |
RegionCallback region_callback, |
- ObjectSlotCallback slot_callback) { |
+ ObjectSlotCallback slot_callback, |
+ bool clear_maps) { |
Address visitable_start = page->area_start(); |
Address end_of_page = page->area_end(); |
@@ -520,7 +532,8 @@ void StoreBuffer::FindPointersToNewSpaceOnPage( |
// After calling this the special garbage section may have moved. |
(this->*region_callback)(visitable_start, |
visitable_end, |
- slot_callback); |
+ slot_callback, |
+ clear_maps); |
if (visitable_end >= space->top() && visitable_end < space->limit()) { |
visitable_end = space->limit(); |
visitable_start = visitable_end; |
@@ -551,13 +564,15 @@ void StoreBuffer::FindPointersToNewSpaceOnPage( |
if (visitable_start != visitable_end) { |
(this->*region_callback)(visitable_start, |
visitable_end, |
- slot_callback); |
+ slot_callback, |
+ clear_maps); |
} |
} |
void StoreBuffer::IteratePointersInStoreBuffer( |
- ObjectSlotCallback slot_callback) { |
+ ObjectSlotCallback slot_callback, |
+ bool clear_maps) { |
Address* limit = old_top_; |
old_top_ = old_start_; |
{ |
@@ -570,6 +585,9 @@ void StoreBuffer::IteratePointersInStoreBuffer( |
Object* object = *slot; |
if (heap_->InFromSpace(object)) { |
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object); |
+ // The new space object was not promoted if it still contains a map |
+ // pointer. Clear the map field now lazily. |
+ if (clear_maps) ClearDeadObject(heap_object); |
slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object); |
if (heap_->InNewSpace(*slot)) { |
EnterDirectlyIntoStoreBuffer(reinterpret_cast<Address>(slot)); |
@@ -582,6 +600,18 @@ void StoreBuffer::IteratePointersInStoreBuffer( |
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. |
@@ -590,7 +620,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); |
+ IteratePointersInStoreBuffer(slot_callback, clear_maps); |
// 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 |
@@ -619,7 +649,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { |
ASSERT(array->IsFixedArray()); |
Address start = array->address(); |
Address end = start + array->Size(); |
- FindPointersToNewSpaceInRegion(start, end, slot_callback); |
+ FindPointersToNewSpaceInRegion(start, end, slot_callback, clear_maps); |
} else { |
Page* page = reinterpret_cast<Page*>(chunk); |
PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner()); |
@@ -629,7 +659,8 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { |
(owner == heap_->map_space() ? |
&StoreBuffer::FindPointersToNewSpaceInMapsRegion : |
&StoreBuffer::FindPointersToNewSpaceInRegion), |
- slot_callback); |
+ slot_callback, |
+ clear_maps); |
} |
} |
} |