From 7b57b624d1fafa909f1985d12249c6af535edc3b Mon Sep 17 00:00:00 2001 From: "alph@chromium.org" Date: Fri, 28 Jun 2013 12:53:52 +0000 Subject: [PATCH] Heap snapshot: Update user roots definition. Do not define an object as a user root if its context is not present in Global handles. R=mstarzinger@chromium.org, yurys@chromium.org Review URL: https://codereview.chromium.org/17881005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15381 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap-snapshot-generator.cc | 36 ++++++++++++++++++++++-------------- src/heap-snapshot-generator.h | 3 ++- test/cctest/test-heap-profiler.cc | 8 +++++--- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 895c0da..dd8896e 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -961,7 +961,7 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { bool extract_indexed_refs = true; if (obj->IsJSGlobalProxy()) { - ExtractJSGlobalProxyReferences(JSGlobalProxy::cast(obj)); + ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); } else if (obj->IsJSObject()) { ExtractJSObjectReferences(entry, JSObject::cast(obj)); } else if (obj->IsString()) { @@ -996,19 +996,11 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { } -void V8HeapExplorer::ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy) { - // We need to reference JS global objects from snapshot's root. - // We use JSGlobalProxy because this is what embedder (e.g. browser) - // uses for the global object. - Object* object = proxy->map()->prototype(); - bool is_debug_object = false; -#ifdef ENABLE_DEBUGGER_SUPPORT - is_debug_object = object->IsGlobalObject() && - Isolate::Current()->debug()->IsDebugGlobal(GlobalObject::cast(object)); -#endif - if (!is_debug_object) { - SetUserGlobalReference(object); - } +void V8HeapExplorer::ExtractJSGlobalProxyReferences( + int entry, JSGlobalProxy* proxy) { + SetInternalReference(proxy, entry, + "native_context", proxy->native_context(), + JSGlobalProxy::kNativeContextOffset); } @@ -1778,6 +1770,22 @@ void V8HeapExplorer::SetGcSubrootReference( snapshot_->gc_subroot(tag)->index(), child_entry); } + + // Add a shortcut to JS global object reference at snapshot root. + if (child_obj->IsNativeContext()) { + Context* context = Context::cast(child_obj); + GlobalObject* global = context->global_object(); + if (global->IsJSGlobalObject()) { + bool is_debug_object = false; +#ifdef ENABLE_DEBUGGER_SUPPORT + is_debug_object = heap_->isolate()->debug()->IsDebugGlobal(global); +#endif + if (!is_debug_object && !user_roots_.Contains(global)) { + user_roots_.Insert(global); + SetUserGlobalReference(global); + } + } + } } } diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h index d942bbe..d3c8f1b 100644 --- a/src/heap-snapshot-generator.h +++ b/src/heap-snapshot-generator.h @@ -454,7 +454,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { const char* GetSystemEntryName(HeapObject* object); void ExtractReferences(HeapObject* obj); - void ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy); + void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy); void ExtractJSObjectReferences(int entry, JSObject* js_obj); void ExtractStringReferences(int entry, String* obj); void ExtractContextReferences(int entry, Context* context); @@ -532,6 +532,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { SnapshotFillerInterface* filler_; HeapObjectsSet objects_tags_; HeapObjectsSet strong_gc_subroot_names_; + HeapObjectsSet user_roots_; v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; static HeapObject* const kGcRootsObject; diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 2ca6e29..afb06fc 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -92,8 +92,9 @@ class NamedEntriesDetector { static const v8::HeapGraphNode* GetGlobalObject( const v8::HeapSnapshot* snapshot) { CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount()); + // The 0th-child is (GC Roots), 1st is the user root. const v8::HeapGraphNode* global_obj = - snapshot->GetRoot()->GetChild(0)->GetToNode(); + snapshot->GetRoot()->GetChild(1)->GetToNode(); CHECK_EQ(0, strncmp("Object", const_cast( reinterpret_cast(global_obj))->name(), 6)); return global_obj; @@ -658,7 +659,8 @@ TEST(HeapSnapshotJSONSerialization) { " first_edge_indexes[i] = first_edge_index;\n" " first_edge_index += edge_fields_count *\n" " parsed.nodes[i * node_fields_count + edge_count_offset];\n" - "}\n"); + "}\n" + "first_edge_indexes[node_count] = first_edge_index;\n"); CHECK(!meta_analysis_result.IsEmpty()); // A helper function for processing encoded nodes. @@ -682,7 +684,7 @@ TEST(HeapSnapshotJSONSerialization) { "GetChildPosByProperty(\n" " GetChildPosByProperty(\n" " GetChildPosByProperty(" - " parsed.edges[edge_to_node_offset]," + " parsed.edges[edge_fields_count + edge_to_node_offset]," " \"b\", property_type),\n" " \"x\", property_type)," " \"s\", property_type)"); -- 2.7.4