Author: [email protected]
Date: Mon May 4 11:47:50 2009
New Revision: 1846
Modified:
branches/bleeding_edge/src/mark-compact.cc
branches/bleeding_edge/src/mark-compact.h
Log:
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
Modified: branches/bleeding_edge/src/mark-compact.cc
==============================================================================
--- branches/bleeding_edge/src/mark-compact.cc (original)
+++ branches/bleeding_edge/src/mark-compact.cc Mon May 4 11:47:50 2009
@@ -562,19 +562,48 @@
}
-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 @@
#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();
}
Modified: branches/bleeding_edge/src/mark-compact.h
==============================================================================
--- branches/bleeding_edge/src/mark-compact.h (original)
+++ branches/bleeding_edge/src/mark-compact.h Mon May 4 11:47:50 2009
@@ -142,6 +142,7 @@
friend class RootMarkingVisitor;
friend class MarkingVisitor;
+ friend class UnmarkingVisitor;
// Marking operations for objects reachable from roots.
static void MarkLiveObjects();
@@ -155,11 +156,23 @@
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 @@
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
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---