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;
}
-// ----------------------------------------------------------------------------
+// -------------------------------------------------------------------------
// 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'.
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();
}
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
}
-#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.
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
}
}
-#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() {
#endif
PagedSpaces spaces;
while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo();
-
-#ifdef DEBUG
- if (FLAG_verify_global_gc) VerifyHeapAfterRelocatingObjects();
-#endif
}
}
-#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();
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() {
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)
// 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;
#ifdef DEBUG
static void UpdateLiveObjectCount(HeapObject* obj);
- static void VerifyHeapAfterMarkingPhase();
#endif
// We sweep the large object space in the same way whether we are
// 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.
+ //
+ // Before: Live objects are marked and non-live objects are unmarked.
+ //
+ // After: (Non-compacting collection.) Live objects are unmarked,
+ // non-live regions have been added to their space's free
+ // list.
+ //
+ // 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 forwarding address of live objects in the new space is
+ // written to their map word's offset in the inactive
+ // semispace.
//
- // The 3rd word of a page has the page top offset after compaction.
+ // Bookkeeping data is written to the remembered-set are of
+ // eached paged-space page that contains live objects after
+ // compaction:
//
- // 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.
+ // 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 5th and 6th words of a page have the start and end
- // addresses of the first free region in the page.
+ // 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 7th word of a page in old spaces has the forwarding address
- // of the first live object in the page.
+ // The 5th word contains the (nonencoded) forwarding address
+ // of the first live object in the page.
//
- // Live young objects have their forwarding pointers in
- // the from space at the same offset to the beginning of the space.
+ // 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.
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
// 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();
// 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.
// 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);