Chromium Code Reviews| 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 |