Clean up the mark-sweep/compact collector by removing outdated

verification code and updating outdated comments.
Review URL: http://codereview.chromium.org/18502

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1131 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2009-01-23 08:13:12 +00:00
parent 031e72ce99
commit 6b2a2c1fff
2 changed files with 83 additions and 228 deletions

View File

@ -35,16 +35,7 @@
namespace v8 { namespace internal {
#ifdef DEBUG
// The verification code used between phases of the m-c collector does not
// currently work.
//
// TODO(1240833): Fix the heap verification code and turn this into a real
// flag.
static const bool FLAG_verify_global_gc = false;
#endif // DEBUG
// ----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// MarkCompactCollector
bool MarkCompactCollector::compacting_collection_ = false;
@ -177,7 +168,7 @@ void MarkCompactCollector::Finish() {
}
// ----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Phase 1: tracing and marking live objects.
// before: all objects are in normal state.
// after: a live object's map pointer is marked as '00'.
@ -729,10 +720,6 @@ void MarkCompactCollector::MarkLiveObjects() {
symbol_table->IterateElements(&v);
symbol_table->ElementsRemoved(v.PointersRemoved());
#ifdef DEBUG
if (FLAG_verify_global_gc) VerifyHeapAfterMarkingPhase();
#endif
// Remove object groups after marking phase.
GlobalHandles::RemoveObjectGroups();
}
@ -765,46 +752,6 @@ void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
UNREACHABLE();
}
}
void MarkCompactCollector::VerifyHeapAfterMarkingPhase() {
Heap::new_space()->Verify();
Heap::old_pointer_space()->Verify();
Heap::old_data_space()->Verify();
Heap::code_space()->Verify();
Heap::map_space()->Verify();
int live_objects;
#define CHECK_LIVE_OBJECTS(it, expected) \
live_objects = 0; \
while (it.has_next()) { \
HeapObject* obj = HeapObject::cast(it.next()); \
if (obj->IsMarked()) live_objects++; \
} \
ASSERT(live_objects == expected);
SemiSpaceIterator new_it(Heap::new_space(), &CountMarkedCallback);
CHECK_LIVE_OBJECTS(new_it, live_young_objects_);
HeapObjectIterator old_pointer_it(Heap::old_pointer_space(),
&CountMarkedCallback);
CHECK_LIVE_OBJECTS(old_pointer_it, live_old_pointer_objects_);
HeapObjectIterator old_data_it(Heap::old_data_space(), &CountMarkedCallback);
CHECK_LIVE_OBJECTS(old_data_it, live_old_data_objects_);
HeapObjectIterator code_it(Heap::code_space(), &CountMarkedCallback);
CHECK_LIVE_OBJECTS(code_it, live_code_objects_);
HeapObjectIterator map_it(Heap::map_space(), &CountMarkedCallback);
CHECK_LIVE_OBJECTS(map_it, live_map_objects_);
LargeObjectIterator lo_it(Heap::lo_space(), &CountMarkedCallback);
CHECK_LIVE_OBJECTS(lo_it, live_lo_objects_);
#undef CHECK_LIVE_OBJECTS
}
#endif // DEBUG
@ -1325,54 +1272,7 @@ int MarkCompactCollector::IterateLiveObjects(PagedSpace* space,
}
#ifdef DEBUG
static int VerifyMapObject(HeapObject* obj) {
InstanceType type = reinterpret_cast<Map*>(obj)->instance_type();
ASSERT(FIRST_TYPE <= type && type <= LAST_TYPE);
return Map::kSize;
}
void MarkCompactCollector::VerifyHeapAfterEncodingForwardingAddresses() {
AllSpaces spaces;
while (Space* space = spaces.next()) space->Verify();
ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
int live_maps = IterateLiveObjects(Heap::map_space(), &VerifyMapObject);
ASSERT(live_maps == live_map_objects_);
// Verify page headers in paged spaces.
PagedSpaces paged_spaces;
while (PagedSpace* space = paged_spaces.next()) VerifyPageHeaders(space);
}
void MarkCompactCollector::VerifyPageHeaders(PagedSpace* space) {
PageIterator mc_it(space, PageIterator::PAGES_USED_BY_MC);
while (mc_it.has_next()) {
Page* p = mc_it.next();
Address mc_alloc_top = p->mc_relocation_top;
ASSERT(p->ObjectAreaStart() <= mc_alloc_top &&
mc_alloc_top <= p->ObjectAreaEnd());
}
int page_count = 0;
PageIterator it(space, PageIterator::PAGES_IN_USE);
while (it.has_next()) {
Page* p = it.next();
ASSERT(p->mc_page_index == page_count);
page_count++;
// first_forwarded could be 'deadbeed' if no live objects in this page
Address first_forwarded = p->mc_first_forwarded;
ASSERT(first_forwarded == kZapValue ||
space->Contains(first_forwarded));
}
}
#endif
// ----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Phase 3: Update pointers
// Helper class for updating pointers in HeapObjects.
@ -1494,8 +1394,6 @@ void MarkCompactCollector::UpdatePointers() {
ASSERT(live_pointer_olds == live_old_pointer_objects_);
ASSERT(live_codes == live_code_objects_);
ASSERT(live_news == live_young_objects_);
if (FLAG_verify_global_gc) VerifyHeapAfterUpdatingPointers();
#endif
}
@ -1601,19 +1499,7 @@ Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
}
#ifdef DEBUG
void MarkCompactCollector::VerifyHeapAfterUpdatingPointers() {
ASSERT(state_ == UPDATE_POINTERS);
AllSpaces spaces;
while (Space* space = spaces.next()) space->Verify();
PagedSpaces paged_spaces;
while (PagedSpace* space = paged_spaces.next()) VerifyPageHeaders(space);
}
#endif
// ----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Phase 4: Relocate objects
void MarkCompactCollector::RelocateObjects() {
@ -1664,10 +1550,6 @@ void MarkCompactCollector::RelocateObjects() {
#endif
PagedSpaces spaces;
while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo();
#ifdef DEBUG
if (FLAG_verify_global_gc) VerifyHeapAfterRelocatingObjects();
#endif
}
@ -1804,18 +1686,6 @@ int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
}
#ifdef DEBUG
class VerifyCopyingVisitor: public ObjectVisitor {
public:
void VisitPointers(Object** start, Object** end) {
for (Object** p = start; p < end; p++) {
MarkCompactCollector::VerifyCopyingObjects(p);
}
}
};
#endif
int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
int obj_size = obj->Size();
@ -1845,44 +1715,13 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
if (FLAG_gc_verbose) {
PrintF("relocate %p -> %p\n", old_addr, new_addr);
}
if (FLAG_verify_global_gc) {
VerifyCopyingVisitor v;
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
copied_to->Iterate(&v);
}
#endif
return obj_size;
}
#ifdef DEBUG
void MarkCompactCollector::VerifyHeapAfterRelocatingObjects() {
ASSERT(state_ == RELOCATE_OBJECTS);
Heap::new_space()->Verify();
PagedSpaces spaces;
while (PagedSpace* space = spaces.next()) {
space->Verify();
PageIterator it(space, PageIterator::PAGES_IN_USE);
while (it.has_next()) {
Page* p = it.next();
ASSERT_PAGE_OFFSET(p->Offset(p->AllocationTop()));
}
}
}
#endif
#ifdef DEBUG
void MarkCompactCollector::VerifyCopyingObjects(Object** p) {
if (!(*p)->IsHeapObject()) return;
ASSERT(!Heap::InToSpace(*p));
}
#endif // DEBUG
// -----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Phase 5: rebuild remembered sets
void MarkCompactCollector::RebuildRSets() {

View File

@ -44,12 +44,12 @@ class RootMarkingVisitor;
class MarkingVisitor;
// ----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Mark-Compact collector
//
// All methods are static.
class MarkCompactCollector : public AllStatic {
class MarkCompactCollector: public AllStatic {
public:
// Type of functions to compute forwarding addresses of objects in
// compacted spaces. Given an object and its size, return a (non-failure)
@ -127,21 +127,18 @@ class MarkCompactCollector : public AllStatic {
// choosing spaces to compact.
static void Prepare();
// Finishes GC, performs heap verification.
// Finishes GC, performs heap verification if enabled.
static void Finish();
// --------------------------------------------------------------------------
// Phase 1: functions related to marking phase.
// before: Heap is in normal state, collector is 'IDLE'.
// -----------------------------------------------------------------------
// Phase 1: Marking live objects.
//
// The first word of a page in old spaces has the end of
// allocation address of the page.
// Before: The heap has been prepared for garbage collection by
// MarkCompactCollector::Prepare() and is otherwise in its
// normal state.
//
// The word at Chunk::high_ address has the address of the
// first page in the next chunk. (The address is tagged to
// distinguish it from end-of-allocation address).
//
// after: live objects are marked.
// After: Live objects are marked and non-live objects are unmarked.
friend class RootMarkingVisitor;
friend class MarkingVisitor;
@ -206,7 +203,6 @@ class MarkCompactCollector : public AllStatic {
#ifdef DEBUG
static void UpdateLiveObjectCount(HeapObject* obj);
static void VerifyHeapAfterMarkingPhase();
#endif
// We sweep the large object space in the same way whether we are
@ -216,30 +212,50 @@ class MarkCompactCollector : public AllStatic {
// Test whether a (possibly marked) object is a Map.
static inline bool SafeIsMap(HeapObject* object);
// Map transitions from a live map to a dead map must be killed.
// Map transitions from a live map to a dead map must be killed.
// We replace them with a null descriptor, with the same key.
static void ClearNonLiveTransitions();
// --------------------------------------------------------------------------
// Phase 2: functions related to computing and encoding forwarding pointers
// before: live objects' map pointers are marked as '00'
// after: Map pointers of live old and map objects have encoded
// forwarding pointers and map pointers
// -----------------------------------------------------------------------
// Phase 2: Sweeping to clear mark bits and free non-live objects for
// a non-compacting collection, or else computing and encoding
// forwarding addresses for a compacting collection.
//
// The 3rd word of a page has the page top offset after compaction.
// Before: Live objects are marked and non-live objects are unmarked.
//
// The 4th word of a page in the map space has the map index
// of this page in the map table. This word is not used in
// the old space.
// After: (Non-compacting collection.) Live objects are unmarked,
// non-live regions have been added to their space's free
// list.
//
// The 5th and 6th words of a page have the start and end
// addresses of the first free region in the page.
// After: (Compacting collection.) The forwarding address of live
// objects in the paged spaces is encoded in their map word
// along with their (non-forwarded) map pointer.
//
// The 7th word of a page in old spaces has the forwarding address
// of the first live object in the page.
// The forwarding address of live objects in the new space is
// written to their map word's offset in the inactive
// semispace.
//
// Live young objects have their forwarding pointers in
// the from space at the same offset to the beginning of the space.
// Bookkeeping data is written to the remembered-set are of
// eached paged-space page that contains live objects after
// compaction:
//
// The 3rd word of the page (first word of the remembered
// set) contains the relocation top address, the address of
// the first word after the end of the last live object in
// the page after compaction.
//
// The 4th word contains the zero-based index of the page in
// its space. This word is only used for map space pages, in
// order to encode the map addresses in 21 bits to free 11
// bits per map word for the forwarding address.
//
// The 5th word contains the (nonencoded) forwarding address
// of the first live object in the page.
//
// In both the new space and the paged spaces, a linked list
// of live regions is constructructed (linked through
// pointers in the non-live region immediately following each
// live region) to speed further passes of the collector.
// Encodes forwarding addresses of objects in compactable parts of the
// heap.
@ -272,19 +288,21 @@ class MarkCompactCollector : public AllStatic {
static void DeallocateCodeBlock(Address start, int size_in_bytes);
static void DeallocateMapBlock(Address start, int size_in_bytes);
// Phase 2: If we are not compacting the heap, we simply sweep the spaces
// except for the large object space, clearing mark bits and adding
// unmarked regions to each space's free list.
// If we are not compacting the heap, we simply sweep the spaces except
// for the large object space, clearing mark bits and adding unmarked
// regions to each space's free list.
static void SweepSpaces();
#ifdef DEBUG
static void VerifyHeapAfterEncodingForwardingAddresses();
#endif
// --------------------------------------------------------------------------
// Phase 3: function related to updating pointers and decode map pointers
// before: see after phase 2
// after: all pointers are updated to forwarding addresses.
// -----------------------------------------------------------------------
// Phase 3: Updating pointers in live objects.
//
// Before: Same as after phase 2 (compacting collection).
//
// After: All pointers in live objects, including encoded map
// pointers, are updated to point to their target's new
// location. The remembered set area of each paged-space
// page containing live objects still contains bookkeeping
// information.
friend class UpdatingVisitor; // helper for updating visited objects
@ -302,14 +320,17 @@ class MarkCompactCollector : public AllStatic {
// Calculates the forwarding address of an object in an old space.
static Address GetForwardingAddressInOldSpace(HeapObject* obj);
#ifdef DEBUG
static void VerifyHeapAfterUpdatingPointers();
#endif
// --------------------------------------------------------------------------
// Phase 4: functions related to relocating objects
// before: see after phase 3
// after: heap is in a normal state, except remembered set is not built
// -----------------------------------------------------------------------
// Phase 4: Relocating objects.
//
// Before: Pointers to live objects are updated to point to their
// target's new location. The remembered set area of each
// paged-space page containing live objects still contains
// bookkeeping information.
//
// After: Objects have been moved to their new addresses. The
// remembered set area of each paged-space page containing
// live objects still contains bookkeeping information.
// Relocates objects in all spaces.
static void RelocateObjects();
@ -334,18 +355,19 @@ class MarkCompactCollector : public AllStatic {
// Copy a new object.
static int RelocateNewObject(HeapObject* obj);
#ifdef DEBUG
static void VerifyHeapAfterRelocatingObjects();
#endif
// ---------------------------------------------------------------------------
// Phase 5: functions related to rebuilding remembered sets
// -----------------------------------------------------------------------
// Phase 5: Rebuilding remembered sets.
//
// Before: The heap is in a normal state except that remembered sets
// in the paged spaces are not correct.
//
// After: The heap is in a normal state.
// Rebuild remembered set in old and map spaces.
static void RebuildRSets();
#ifdef DEBUG
// ---------------------------------------------------------------------------
// -----------------------------------------------------------------------
// Debugging variables, functions and classes
// Counters used for debugging the marking phase of mark-compact or
// mark-sweep collection.
@ -371,12 +393,6 @@ class MarkCompactCollector : public AllStatic {
// Number of live bytes in this collection.
static int live_bytes_;
static void VerifyPageHeaders(PagedSpace* space);
// Verification functions when relocating objects.
friend class VerifyCopyingVisitor;
static void VerifyCopyingObjects(Object** p);
friend class MarkObjectVisitor;
static void VisitObject(HeapObject* obj);