More special handling of the symbol table during garbage collection.

Mark all objects reachable from the symbols except the symbols
themselves as live (and reachable from strong roots).  This ensures
that if the symbol itself remains alive for any reason, and if it was
a sliced string or cons string backed by an external string, then the
external string will be strongly reachable and therefore not get a
weak reference callback.

Review URL: http://codereview.chromium.org/100344

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1846 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent eb906555
......@@ -562,19 +562,48 @@ bool MarkCompactCollector::MustBeMarked(Object** p) {
}
void MarkCompactCollector::ProcessRoots(RootMarkingVisitor* visitor) {
// Mark the heap roots gray, including global variables, stack variables,
// etc.
Heap::IterateStrongRoots(visitor);
// Helper class to unmark marked objects in a range of pointers but
// not recursively.
class UnmarkingVisitor : public ObjectVisitor {
public:
void VisitPointers(Object** start, Object** end) {
for (Object** p = start; p < end; p++) {
if ((*p)->IsHeapObject() && HeapObject::cast(*p)->IsMarked()) {
MarkCompactCollector::ClearMark(HeapObject::cast(*p));
}
}
}
};
// Take care of the symbol table specially.
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.
//
// 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());
// 1. Mark the prefix of the symbol table gray.
symbol_table->IteratePrefix(visitor);
// 2. Mark the symbol table black (ie, do not push it on the marking stack
// or mark it overflowed).
// 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);
// Mark the heap roots including global variables, stack variables,
// etc., and all objects reachable from them.
Heap::IterateStrongRoots(visitor);
// There may be overflowed objects in the heap. Visit them now.
while (marking_stack.overflowed()) {
RefillMarkingStack();
......@@ -762,21 +791,22 @@ static int CountMarkedCallback(HeapObject* obj) {
#ifdef DEBUG
void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
live_bytes_ += obj->Size();
void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj, int scale) {
ASSERT(scale == -1 || scale == 1);
live_bytes_ += obj->Size() * scale;
if (Heap::new_space()->Contains(obj)) {
live_young_objects_++;
live_young_objects_ += scale;
} else if (Heap::map_space()->Contains(obj)) {
ASSERT(obj->IsMap());
live_map_objects_++;
live_map_objects_ += scale;
} else if (Heap::old_pointer_space()->Contains(obj)) {
live_old_pointer_objects_++;
live_old_pointer_objects_ += scale;
} else if (Heap::old_data_space()->Contains(obj)) {
live_old_data_objects_++;
live_old_data_objects_ += scale;
} else if (Heap::code_space()->Contains(obj)) {
live_code_objects_++;
live_code_objects_ += scale;
} else if (Heap::lo_space()->Contains(obj)) {
live_lo_objects_++;
live_lo_objects_ +=scale;
} else {
UNREACHABLE();
}
......
......@@ -142,6 +142,7 @@ class MarkCompactCollector: public AllStatic {
friend class RootMarkingVisitor;
friend class MarkingVisitor;
friend class UnmarkingVisitor;
// Marking operations for objects reachable from roots.
static void MarkLiveObjects();
......@@ -155,11 +156,23 @@ class MarkCompactCollector: public AllStatic {
static inline void SetMark(HeapObject* obj) {
tracer_->increment_marked_count();
#ifdef DEBUG
UpdateLiveObjectCount(obj);
UpdateLiveObjectCount(obj, 1);
#endif
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
......@@ -202,7 +215,10 @@ class MarkCompactCollector: public AllStatic {
static bool MustBeMarked(Object** p);
#ifdef DEBUG
static void UpdateLiveObjectCount(HeapObject* obj);
// The scale argument is positive 1 if we are marking an object and
// -1 if we are clearing the mark bit of an object that we didn't
// actually want marked.
static void UpdateLiveObjectCount(HeapObject* obj, int scale);
#endif
// We sweep the large object space in the same way whether we are
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment