Index: src/heap.cc |
=================================================================== |
--- src/heap.cc (revision 6858) |
+++ src/heap.cc (working copy) |
@@ -5181,32 +5181,24 @@ |
} |
-#ifdef DEBUG |
+#if defined(DEBUG) || defined(LIVE_OBJECT_LIST) |
-static bool search_for_any_global; |
-static Object* search_target; |
-static bool found_target; |
-static List<Object*> object_stack(20); |
- |
- |
-// Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. |
-static const int kMarkTag = 2; |
- |
-static void MarkObjectRecursively(Object** p); |
-class MarkObjectVisitor : public ObjectVisitor { |
- public: |
- void VisitPointers(Object** start, Object** end) { |
- // Copy all HeapObject pointers in [start, end) |
- for (Object** p = start; p < end; p++) { |
- if ((*p)->IsHeapObject()) |
- MarkObjectRecursively(p); |
- } |
+void PathTracer::TracePathFrom(Object** root) { |
+ if (search_for_any_global_) { |
mnaganov (inactive)
2011/02/21 10:59:46
Using two version of the constructor instead of ru
marklam
2011/02/21 17:45:15
This is code that was originally there from the Ma
|
+ ASSERT(search_target_ == NULL); |
+ } else { |
+ ASSERT(search_target_->IsHeapObject()); |
} |
-}; |
+ found_target_in_trace_ = false; |
+ object_stack_.Clear(); |
-static MarkObjectVisitor mark_visitor; |
+ MarkRecursively(root); |
+ UnmarkRecursively(root); |
+ ProcessResults(); |
+} |
-static void MarkObjectRecursively(Object** p) { |
+ |
+void PathTracer::MarkRecursively(Object** p) { |
if (!(*p)->IsHeapObject()) return; |
HeapObject* obj = HeapObject::cast(*p); |
@@ -5215,14 +5207,17 @@ |
if (!map->IsHeapObject()) return; // visited before |
- if (found_target) return; // stop if target found |
- object_stack.Add(obj); |
- if ((search_for_any_global && obj->IsJSGlobalObject()) || |
- (!search_for_any_global && (obj == search_target))) { |
- found_target = true; |
+ if (found_target_in_trace_) return; // stop if target found |
+ object_stack_.Add(obj); |
+ if ((search_for_any_global_ && obj->IsJSGlobalObject()) || |
+ (!search_for_any_global_ && (obj == search_target_))) { |
+ found_target_in_trace_ = true; |
+ found_target_ = true; |
return; |
} |
+ bool is_global_context = obj->IsGlobalContext(); |
+ |
// not visited yet |
Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); |
@@ -5230,31 +5225,29 @@ |
obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); |
- MarkObjectRecursively(&map); |
+ // Scan the object body. |
+ if (is_global_context && skip_weak_refs_) { |
+ // This is specialized to scan Context's properly. |
+ Object** start = reinterpret_cast<Object**>(obj->address() + |
+ Context::kHeaderSize); |
+ Object** end = reinterpret_cast<Object**>(obj->address() + |
+ Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize); |
+ mark_visitor.VisitPointers(start, end); |
+ } else { |
+ obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), |
+ &mark_visitor); |
+ } |
- obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), |
- &mark_visitor); |
+ // Scan the map after the body because the body is a lot more interesting |
+ // when doing leak detection. |
+ MarkRecursively(&map); |
- if (!found_target) // don't pop if found the target |
- object_stack.RemoveLast(); |
+ if (!found_target_in_trace_) // don't pop if found the target |
+ object_stack_.RemoveLast(); |
} |
-static void UnmarkObjectRecursively(Object** p); |
-class UnmarkObjectVisitor : public ObjectVisitor { |
- public: |
- void VisitPointers(Object** start, Object** end) { |
- // Copy all HeapObject pointers in [start, end) |
- for (Object** p = start; p < end; p++) { |
- if ((*p)->IsHeapObject()) |
- UnmarkObjectRecursively(p); |
- } |
- } |
-}; |
- |
-static UnmarkObjectVisitor unmark_visitor; |
- |
-static void UnmarkObjectRecursively(Object** p) { |
+void PathTracer::UnmarkRecursively(Object** p) { |
if (!(*p)->IsHeapObject()) return; |
HeapObject* obj = HeapObject::cast(*p); |
@@ -5273,7 +5266,7 @@ |
obj->set_map(reinterpret_cast<Map*>(map_p)); |
- UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); |
+ UnmarkRecursively(reinterpret_cast<Object**>(&map_p)); |
obj->IterateBody(Map::cast(map_p)->instance_type(), |
obj->SizeFromMap(Map::cast(map_p)), |
@@ -5281,55 +5274,30 @@ |
} |
-static void MarkRootObjectRecursively(Object** root) { |
- if (search_for_any_global) { |
- ASSERT(search_target == NULL); |
- } else { |
- ASSERT(search_target->IsHeapObject()); |
- } |
- found_target = false; |
- object_stack.Clear(); |
- |
- MarkObjectRecursively(root); |
- UnmarkObjectRecursively(root); |
- |
- if (found_target) { |
+void PathTracer::ProcessResults() { |
+ if (found_target_) { |
PrintF("=====================================\n"); |
PrintF("==== Path to object ====\n"); |
PrintF("=====================================\n\n"); |
- ASSERT(!object_stack.is_empty()); |
- for (int i = 0; i < object_stack.length(); i++) { |
+ ASSERT(!object_stack_.is_empty()); |
+ for (int i = 0; i < object_stack_.length(); i++) { |
if (i > 0) PrintF("\n |\n |\n V\n\n"); |
- Object* obj = object_stack[i]; |
+ Object* obj = object_stack_[i]; |
obj->Print(); |
} |
PrintF("=====================================\n"); |
} |
} |
+#endif // DEBUG || LIVE_OBJECT_LIST |
-// Helper class for visiting HeapObjects recursively. |
-class MarkRootVisitor: public ObjectVisitor { |
- public: |
- void VisitPointers(Object** start, Object** end) { |
- // Visit all HeapObject pointers in [start, end) |
- for (Object** p = start; p < end; p++) { |
- if ((*p)->IsHeapObject()) |
- MarkRootObjectRecursively(p); |
- } |
- } |
-}; |
- |
- |
+#ifdef DEBUG |
// Triggers a depth-first traversal of reachable objects from roots |
// and finds a path to a specific heap object and prints it. |
void Heap::TracePathToObject(Object* target) { |
- search_target = target; |
- search_for_any_global = false; |
- |
- MarkRootVisitor root_visitor; |
- IterateRoots(&root_visitor, VISIT_ONLY_STRONG); |
+ PathTracer tracer(target, false, PathTracer::kFindAll, false); |
+ IterateRoots(&tracer, VISIT_ONLY_STRONG); |
} |
@@ -5337,11 +5305,8 @@ |
// and finds a path to any global object and prints it. Useful for |
// determining the source for leaks of global objects. |
void Heap::TracePathToGlobal() { |
- search_target = NULL; |
- search_for_any_global = true; |
- |
- MarkRootVisitor root_visitor; |
- IterateRoots(&root_visitor, VISIT_ONLY_STRONG); |
+ PathTracer tracer(NULL, true, PathTracer::kFindAll, false); |
+ IterateRoots(&tracer, VISIT_ONLY_STRONG); |
} |
#endif |