From 3af69aed22c1bc16c8ae0642648abc6e496356d7 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Tue, 5 May 2009 05:13:09 +0000 Subject: [PATCH] Improved, safer handling of the symbol table. The symbols themselves are not treated as roots, but all their subparts are. Review URL: http://codereview.chromium.org/108002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mark-compact.cc | 54 +++++++++++++++++++++++++++------------------ src/mark-compact.h | 17 ++++---------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/mark-compact.cc b/src/mark-compact.cc index 8c0231e0f3..94cf315a86 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -562,48 +562,58 @@ bool MarkCompactCollector::MustBeMarked(Object** p) { } -// Helper class to unmark marked objects in a range of pointers but -// not recursively. -class UnmarkingVisitor : public ObjectVisitor { +class SymbolMarkingVisitor : public ObjectVisitor { public: void VisitPointers(Object** start, Object** end) { + MarkingVisitor marker; for (Object** p = start; p < end; p++) { - if ((*p)->IsHeapObject() && HeapObject::cast(*p)->IsMarked()) { - MarkCompactCollector::ClearMark(HeapObject::cast(*p)); - } + if (!(*p)->IsHeapObject()) continue; + + HeapObject* object = HeapObject::cast(*p); + // If the object is marked, we have marked or are in the process + // of marking subparts. + if (object->IsMarked()) continue; + + // The object is unmarked, we do not need to unmark to use its + // map. + Map* map = object->map(); + object->IterateBody(map->instance_type(), + object->SizeFromMap(map), + &marker); } } }; -void MarkCompactCollector::ProcessRoots(RootMarkingVisitor* visitor) { - // Handle the symbol table specially. Mark the prefix and the - // symbol table itself. Do not mark the symbol table entries, but - // do explicitly mark all other objects reachable from them. - // +void MarkCompactCollector::MarkSymbolTable() { // Objects reachable from symbols are marked as live so as to ensure // that if the symbol itself remains alive after GC for any reason, // and if it is a sliced string or a cons string backed by an // external string (even indirectly), then the external string does // not receive a weak reference callback. SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table()); - // First mark everything reachable from the symbol table, then - // unmark just the elements themselves. - symbol_table->Iterate(visitor); - // There may be overflowed objects in the heap. Visit them now. - while (marking_stack.overflowed()) { - RefillMarkingStack(); - EmptyMarkingStack(visitor->stack_visitor()); - } - UnmarkingVisitor unmarking_visitor; - symbol_table->IterateElements(&unmarking_visitor); // Mark the symbol table itself. SetMark(symbol_table); + // Explicitly mark the prefix. + MarkingVisitor marker; + symbol_table->IteratePrefix(&marker); + ProcessMarkingStack(&marker); + // Mark subparts of the symbols but not the symbols themselves + // (unless reachable from another symbol). + SymbolMarkingVisitor symbol_marker; + symbol_table->IterateElements(&symbol_marker); + ProcessMarkingStack(&marker); +} + +void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { // Mark the heap roots including global variables, stack variables, // etc., and all objects reachable from them. Heap::IterateStrongRoots(visitor); + // Handle the symbol table specially. + MarkSymbolTable(); + // There may be overflowed objects in the heap. Visit them now. while (marking_stack.overflowed()) { RefillMarkingStack(); @@ -744,7 +754,7 @@ void MarkCompactCollector::MarkLiveObjects() { ASSERT(!marking_stack.overflowed()); RootMarkingVisitor root_visitor; - ProcessRoots(&root_visitor); + MarkRoots(&root_visitor); // The objects reachable from the roots are marked black, unreachable // objects are white. Mark objects reachable from object groups with at diff --git a/src/mark-compact.h b/src/mark-compact.h index 1057241cd1..94505b11e7 100644 --- a/src/mark-compact.h +++ b/src/mark-compact.h @@ -161,18 +161,6 @@ class MarkCompactCollector: public AllStatic { obj->SetMark(); } - // Used to clear mark bits during marking for objects that are not - // actually live. Since it updates bookkeeping state, it is not - // used when clearing mark bits on live objects (eg, during - // sweeping). - static inline void ClearMark(HeapObject* obj) { - obj->ClearMark(); - tracer_->decrement_marked_count(); -#ifdef DEBUG - UpdateLiveObjectCount(obj, -1); -#endif - } - // Creates back pointers for all map transitions, stores them in // the prototype field. The original prototype pointers are restored // in ClearNonLiveTransitions(). All JSObject maps @@ -185,7 +173,10 @@ class MarkCompactCollector: public AllStatic { static void MarkDescriptorArray(DescriptorArray* descriptors); // Mark the heap roots and all objects reachable from them. - static void ProcessRoots(RootMarkingVisitor* visitor); + static void MarkRoots(RootMarkingVisitor* visitor); + + // Mark the symbol table specially. References to symbols are weak. + static void MarkSymbolTable(); // Mark objects in object groups that have at least one object in the // group marked.