Index: src/mark-compact.cc |
=================================================================== |
--- src/mark-compact.cc (revision 6554) |
+++ src/mark-compact.cc (working copy) |
@@ -101,9 +101,9 @@ |
if (FLAG_collect_maps) ClearNonLiveTransitions(); |
+ SweepSpaces(); |
SweepLargeObjectSpace(); |
Vyacheslav Egorov (Chromium)
2011/02/02 13:15:47
You can now move SweepLargeObjectSpace into SweepS
Erik Corry
2011/02/03 13:21:17
Done.
|
- SweepSpaces(); |
PcToCodeCache::FlushPcToCodeCache(); |
Finish(); |
@@ -416,7 +416,8 @@ |
// Since we don't have the object's start, it is impossible to update the |
// page dirty marks. Therefore, we only replace the string with its left |
- // substring when page dirty marks do not change. |
+ // substring when page dirty marks do not change. TODO(gc): Seems like we |
Vyacheslav Egorov (Chromium)
2011/02/02 13:15:47
move todo to the new line
Erik Corry
2011/02/03 13:21:17
Done.
|
+ // could relax this restriction with store buffers. |
Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first(); |
if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object; |
@@ -1430,9 +1431,7 @@ |
void MarkCompactCollector::SweepLargeObjectSpace() { |
#ifdef DEBUG |
- ASSERT(state_ == MARK_LIVE_OBJECTS); |
- state_ = |
- compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES; |
+ ASSERT(state_ == SWEEP_SPACES); |
#endif |
// Deallocate unmarked objects and clear marked bits for marked objects. |
Heap::lo_space()->FreeUnmarkedObjects(); |
@@ -1509,14 +1508,18 @@ |
// We scavange new space simultaneously with sweeping. This is done in two |
// passes. |
+// |
// The first pass migrates all alive objects from one semispace to another or |
-// promotes them to old space. Forwading address is written directly into |
-// first word of object without any encoding. If object is dead we are writing |
+// promotes them to old space. Forwarding address is written directly into |
+// first word of object without any encoding. If object is dead we write |
// NULL as a forwarding address. |
-// The second pass updates pointers to new space in all spaces. It is possible |
-// to encounter pointers to dead objects during traversal of dirty regions we |
-// should clear them to avoid encountering them during next dirty regions |
-// iteration. |
+// |
+// The second pass updates pointers to new space in all spaces. It is possible |
+// to encounter pointers to dead new space objects during traversal of pointers |
+// to new space. We should clear them to avoid encountering them during next |
+// pointer iteration. This is an issue if the store buffer overflows and we |
+// have to scan the entire old space, including dead objects, looking for |
+// pointers to new space. |
static void MigrateObject(Address dst, |
Address src, |
int size, |
@@ -1526,7 +1529,6 @@ |
} else { |
Heap::CopyBlock(dst, src, size); |
} |
- |
Memory::Address_at(src) = dst; |
} |
@@ -1581,23 +1583,27 @@ |
}; |
-// Visitor for updating pointers from live objects in old spaces to new space. |
-// It can encounter pointers to dead objects in new space when traversing map |
-// space (see comment for MigrateObject). |
-static void UpdatePointerToNewGen(HeapObject** p) { |
- if (!(*p)->IsHeapObject()) return; |
+static void UpdatePointerToNewGen(HeapObject** p, HeapObject* object) { |
+ ASSERT(Heap::InFromSpace(object)); |
+ ASSERT(*p == object); |
- Address old_addr = (*p)->address(); |
- ASSERT(Heap::InFromSpace(*p)); |
+ Address old_addr = object->address(); |
Address new_addr = Memory::Address_at(old_addr); |
- if (new_addr == NULL) { |
- // We encountered pointer to a dead object. Clear it so we will |
- // not visit it again during next iteration of dirty regions. |
- *p = NULL; |
+ // 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. |
+ if (new_addr != NULL) { |
+ *p = HeapObject::FromAddress(new_addr); |
+ if (Heap::InNewSpace(new_addr)) { |
+ StoreBuffer::EnterDirectlyIntoStoreBuffer(reinterpret_cast<Address>(p)); |
+ } |
} else { |
- *p = HeapObject::FromAddress(new_addr); |
+ // We have to zap this pointer, because the store buffer may overflow later, |
+ // and then we have to scan the entire heap and we don't want to find |
+ // spurious newspace pointers in the old space. |
+ *p = HeapObject::FromAddress(NULL); // Fake heap object not in new space. |
} |
} |
@@ -1685,6 +1691,7 @@ |
false); |
} else { |
size = object->Size(); |
+ // Mark dead objects in the new space with null in their map field. |
Memory::Address_at(current) = NULL; |
} |
} |
@@ -1704,14 +1711,11 @@ |
// Update roots. |
Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); |
- // Update pointers in old spaces. |
- Heap::IterateDirtyRegions(Heap::old_pointer_space(), |
- &Heap::IteratePointersInDirtyRegion, |
- &UpdatePointerToNewGen, |
- Heap::WATERMARK_SHOULD_BE_VALID); |
+ { |
+ StoreBufferRebuildScope scope; |
+ StoreBuffer::IteratePointersToNewSpace(&UpdatePointerToNewGen); |
+ } |
- Heap::lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen); |
- |
// Update pointers from cells. |
HeapObjectIterator cell_iterator(Heap::cell_space()); |
for (HeapObject* cell = cell_iterator.next(); |
@@ -2029,8 +2033,9 @@ |
void MarkCompactCollector::SweepSpaces() { |
GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
- |
- ASSERT(state_ == SWEEP_SPACES); |
+#ifdef DEBUG |
+ state_ = SWEEP_SPACES; |
+#endif |
ASSERT(!IsCompacting()); |
// Noncompacting collections simply sweep the spaces to clear the mark |
// bits and free the nonlive blocks (for old and map spaces). We sweep |
@@ -2051,11 +2056,6 @@ |
// TODO(gc): Implement specialized sweeper for map space. |
SweepSpace(Heap::map_space(), PRECISE); |
- Heap::IterateDirtyRegions(Heap::map_space(), |
- &Heap::IteratePointersInDirtyMapsRegion, |
- &UpdatePointerToNewGen, |
- Heap::WATERMARK_SHOULD_BE_VALID); |
- |
ASSERT(live_map_objects_size_ <= Heap::map_space()->Size()); |
} |